Building a Production REST API with Node.js and Express in 2026
Layered architecture, validation, error handling, auth, rate limiting, observability — the patterns I use to ship Node.js + Express APIs that don't fall over in production.
Why Express, in 2026
I keep getting asked: "Express? Still? Why not Hono / Fastify / Bun?"
Express is still the most common Node.js HTTP framework I see in production codebases, by a wide margin. It's not the fastest, it's not the most modern, but it's stable, mature, and every Node engineer knows it. For a senior who needs to onboard a junior in two days, Express wins.
That said, I'll mention where Fastify or Hono make sense at the end. The patterns in this post apply to all three; Express is just the example.
The architecture I keep coming back to
Five layers, each with one responsibility:
A request flows: route → controller → service → repository → DB → service → controller → response.
The reason for this separation is testability. Services don't know about HTTP, so you can unit-test business logic without booting Express. Repositories don't know about services, so you can swap MongoDB for PostgreSQL without touching business logic.
Validation: at the boundary, not throughout
Bad code I see all the time has validation scattered across the service. Better: validate at the route boundary with Zod, so your service receives already-validated data and stays clean.
I use Zod everywhere now. Joi was the standard for years; Zod is faster, has better TypeScript inference, and the schema syntax is more readable.
Error handling that doesn't suck
The Express default — a single next(err) and a global handler — is fine but easy to misuse. The pattern:
if (!user) throw new NotFoundError("User")The benefit: known errors have clear codes. Unknown errors get logged with context and a generic message goes back to the client. No leaking stack traces in production.
Authentication: JWT with refresh, not session cookies
For a stateless REST API, JWT with a short-lived access token (15 min) and a long-lived refresh token (7 days) stored in an HttpOnly cookie is the pattern I default to.
When NOT to use this: if you only need browser clients on a single domain, a simple HttpOnly session cookie is simpler and more secure (no JWT footguns). JWT shines when you have multiple clients (web + mobile + third-party API consumers).
Rate limiting: at multiple layers
A single layer of rate limiting is brittle. I use three:
Don't roll your own — express-rate-limit with a Redis store handles 99% of cases.
Observability: logs, metrics, traces
The minimum viable observability stack for a Node API:
Where to ship the data: Grafana Cloud (free tier is enough for most projects), Datadog (expensive but excellent), or Honeycomb (best for tracing).
The DB layer
For new projects in 2026 I'm using:
Mongoose is fine but Drizzle's type inference is better than Mongoose's schemas, and for SQL-relational data, Postgres is the right answer.
When to reach for Fastify or Hono instead
What I ship for clients
A typical Node.js + Express API engagement looks like:
If you're starting a new Node.js + Express project and want a senior to architect it, reach out — backend engagements are part of my core service offering.
TL;DR
You might also like
MongoDB Indexing Strategies That Actually Save You Money
Real-world MongoDB indexing patterns I've used to drop query times by 100x and Atlas bills by 60%. Compound indexes, ESR rule, partial indexes, TTL — and the indexes you should never create.
How to Hire a Blockchain Developer in Pakistan in 2026
A practical guide to hiring blockchain developers from Pakistan in 2026 — where to find them, what rates to expect, red flags, contract structure, and how to evaluate Solidity skill in 30 minutes.
React Server Components in Next.js 14: Production Patterns That Work
When to use Server Components vs Client Components in Next.js 14, the patterns that survive production, and the foot-guns I keep tripping over after shipping 8+ App Router projects.