intermediate
Express middleware
Explain middleware order, request mutation, short-circuiting, async handlers, next(), and boundary concerns like auth and parsing.
Middleware functions have signature `(req, res, next)` and run in registration order. Each can mutate `req`/`res`, end the response, or call `next()` to continue. Order matters: body parsers and auth must run before route handlers.
app.use(express.json({ limit: '100kb' }));
app.use(requestId);
app.use('/api', authMiddleware, apiRouter);
Async middleware must forward errors — either `next(err)` in catch blocks or wrap with a helper so rejected promises reach error middleware. Calling `next()` after `res.send()` can cause double-send bugs.
On interviews: describe the middleware stack as a pipeline, when to short-circuit (auth failure, validation), and how `app.use` versus route-level middleware scopes concerns.
Common pitfalls: wrong order (routes before parsers), unhandled async rejections, and global middleware doing too much per request.
The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.
Checklist:
- Register parsers and security middleware first.
- Wrap async handlers to call `next(err)`.
- Scope auth to route prefixes where possible.
- Never call `next()` after sending a response.