How does Express middleware actually work?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Middleware are functions receiving (req, res, next), executing in registration order. Each either ends the response or calls next() to pass control down the stack. Errors skip ahead to four-argument error middleware via next(err).
Detailed explanation
Express maintains an ordered array of handlers matched against method+path. Each request flows through them sequentially: middleware may mutate req/res (attach user from token, parse body, log timing), terminate with res.send(), or invoke next() continuing the chain. Path prefixes scope middleware (app.use('/api', router)); Router instances nest composable stacks. The error variant is signature-based: handlers declaring exactly (err, req, res, next) receive anything passed to next(err) — normal handlers between are skipped, enabling centralized error formatting at the end of the stack. Ordering bugs dominate real issues: body parser registered after routes sees empty bodies; error handler placed early never triggers. Forgetting next() hangs requests until timeout. Modern alternatives (Fastify hooks, Koa's async composition, Hono) formalize the same pipeline concept — understanding request lifecycle transfers directly.
Example
app.use(requestLogger); // 1st: logs everything
app.use(express.json()); // 2nd: parses bodies
app.use('/api', apiRouter); // scoped routes
app.use((req, res) => res.status(404).end()); // fallthrough
app.use((err, req, res, _next) => { // error handler: 4 args!
console.error(err);
res.status(500).json({ error: 'Internal error' });
});
function requestLogger(req, _res, next) {
console.log(`${req.method} ${req.url}`);
next();
}Interview tip
Walk one request through the stack aloud, then highlight the two classic gotchas — ordering matters and the 4-argument error signature is how errors get routed.
Common mistakes
- Registering json() parser after routes.
- Defining error middleware with three arguments.