intermediate
Middleware
Compose request handlers for cross-cutting concerns while controlling order, ownership, short-circuiting, and side effects.
Middleware functions wrap request handling with signature `(req, res, next) => void` (Express-style) or framework hooks — they compose cross-cutting behavior in explicit order.
app.use(requestId());
app.use(express.json({ limit: '1mb' }));
app.use(authenticate);
app.get('/orders/:id', authorize('orders:read'), getOrder);
function asyncHandler(fn) {
return (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
}
Order matters: body parsing before validation; auth before authorization; error middleware last (four-arg handler). Short-circuit by sending a response without calling `next()`.
Frameworks differ (Fastify hooks, Koa onion model) but the design question is the same: who owns side effects and failure paths.
On interviews: diagram middleware order for auth + validation; explain error propagation to centralized handler; contrast global vs route-scoped middleware.
Common pitfalls: calling `next()` after response sent; async middleware without error forwarding; god middleware that knows every route.
The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.
Checklist:
- Single responsibility per middleware.
- Document required order in README or module.
- Centralize error formatting.
- Avoid mutable baggage on `req` without types/discipline.