The Shapes You'll See In Real Code
Middleware Patterns
A tour of the middleware patterns that show up across Express codebases.
What you'll learn
- Recognize common patterns
- Pick the right pattern for the job
- Avoid common traps
Five patterns you’ll see repeatedly in real Express code.
1. Attach a Computed Property
function attachRequestId(req, res, next) {
req.id = randomUUID();
res.set("x-request-id", req.id);
next();
} Pre-compute something every later handler will use.
2. Tap Into the Response
function metrics(req, res, next) {
const start = Date.now();
res.on("finish", () => {
histogramRequestDuration.observe(
{ route: req.route?.path, status: res.statusCode },
Date.now() - start
);
});
next();
} Hook res.on("finish") for metrics, logging, audit trails.
3. Wrap a Sub-Chain
function transactional(handler) {
return async (req, res, next) => {
const tx = await db.beginTransaction();
try {
req.tx = tx;
await handler(req, res, next);
await tx.commit();
} catch (err) {
await tx.rollback();
next(err);
}
};
}
app.post("/transfer", transactional(transferHandler)); Wrap the actual handler in pre/post logic. Useful for DB transactions.
4. Compose Multiple
function compose(...mws) {
return mws; // Express already accepts arrays
}
const adminWrite = compose(
requireAuth,
requireAdmin,
audit("admin-write"),
);
app.post("/admin/users", adminWrite, createUser); Express handles arrays automatically — middleware composition for free.
5. Branch on Content Type
function parseBody(req, res, next) {
const type = req.get("content-type") ?? "";
if (type.startsWith("application/json")) return express.json()(req, res, next);
if (type.startsWith("application/x-www-form-urlencoded")) return express.urlencoded()(req, res, next);
if (type.startsWith("text/")) return express.text()(req, res, next);
next();
} Manually pick the right parser based on the request. Rarely needed — but the mechanism is good to know.
Antipatterns
Long Middleware Chains
If a route has 8 middlewares in front of the handler, it’s hard to read and slow to add to. Split logic into the handler itself or into well-named bundles.
Hidden Side Effects
Middleware that mutates req in surprising ways becomes a debug
nightmare. Document what your middleware adds to req.
Sync File I/O
Don’t readFileSync in middleware — blocks the event loop on every
request.
End of Chapter
You can now compose Express middleware with confidence. Next chapter: building real REST APIs.
Building REST APIs →