Node backends that do not fall over at 3am.
Express, Fastify, NestJS, or hand-rolled. We pick what survives observability and adversarial users, not what sounds cool on a conference talk.
The shape of a Node backend that has grown for two years.
Most production Node backends have grown from a single index.js file into a codebase of 200 routes, three databases, two queues, and one event bus. The team that built it is half the team it was a year ago. Routes do too much. Errors do not bubble up cleanly. The DB connection pool runs out at 10pm on Tuesdays for reasons nobody has time to investigate. We have inherited this codebase shape more times than we have started one fresh.
What changes when a Metafic pod is in your repo.
Strict TypeScript, no any
Strict mode on from week one. We rewrite enough of the type definitions to make the IDE useful, even on legacy code.
Boundaries with Zod or io-ts at every edge
Validation on the API layer, validation on database deserialization, validation between services. "Why is this field undefined" becomes a build error, not a 2am page.
Structured logging plus traces
Pino, OpenTelemetry, hooked into Honeycomb or your stack of choice. Every request has a trace ID. Every database call shows up on the trace.
Job queues for everything async
BullMQ, Inngest, or your own. Email sends, webhook deliveries, batch jobs. Anything over 200ms goes off the request path.
DB connection pooling tuned to actual load
Most production Node services run at 2x to 10x the connection-pool size they need. We profile and tune.
Who is on the pod for this work.
Pods scale up from here for Enterprise engagements.
Has owned multiple Node services at scale. Specific opinions on which framework lives where.
5+ years Node, comfortable with both API design and database internals.
Writes integration tests that hit real Postgres in CI, not mocks.
Tuned to read your route definitions and propose validation schemas, error mappings, and telemetry hooks.
The bugs that bite this stack.
Express middleware order silently shifting
Middleware added over time without revisiting order. CORS preflight ends up running auth, the logger fires after the error has been swallowed. We straighten this out in week one.
Promise rejections eating themselves
Older Node code is full of forgotten .catch() or unhandled await. The process keeps running but quietly drops work. We add the safety net.
ORM N+1 queries hiding under load
Prisma, TypeORM, Drizzle. All three make N+1 too easy by default. We add database query tests that catch them in CI.
Health checks that do not check health
A /health endpoint that only confirms the process is up. Real health means database reachable, Redis up, downstream services responsive.
Honest about scope.
We will not rewrite from Express to NestJS just because. The framework is rarely the bottleneck. We will rewrite if a custom microservices abstraction has become a second framework that nobody owns.
Common questions.
Should we move off Express?
Probably not. Express is fine for 95% of services. The exception is real-time-heavy work (Fastify or uWebSockets), or strongly opinionated team conventions (NestJS).
Bun or Deno worth it?
Not yet for production for most teams. The performance is real, the ecosystem gap is also real. We have shipped Bun in production for one client; we would do it again for a specific workload, not as a default.
Postgres or MongoDB?
Postgres for almost all new work. MongoDB if the data really is document-shaped and write patterns are append-mostly. We rarely see Mongo win on a fresh choice.
What ORM in 2026?
Drizzle if you are starting fresh and want SQL transparency. Prisma if your team values DX over fine control. Raw SQL with a small query builder for high-throughput services.
Ready to scope it?
A 25-minute call. We will tell you what we would do, what we would not, and whether a pod is the right shape.
Or stay in the loop. One engineering teardown a week.