Middleware patterns form the backbone of request-response pipelines in modern backend applications—sitting between the client and your core business logic to handle cross-cutting concerns like authentication, logging, and error handling. Every HTTP request flows through a chain of middleware functions that can inspect, transform, or short-circuit the request before it reaches your endpoints. The key mental model: middleware is composable layering—each layer adds one distinct capability, and the order matters tremendously because authentication must happen before authorization, logging before response compression, and error handling should wrap everything.
What This Cheat Sheet Covers
This topic spans 17 focused tables and 136 indexed concepts. Below is a complete table-by-table outline of this topic, spanning foundational concepts through advanced details.
Table 1: Core Middleware Architecture
| Pattern | Example | Description |
|---|---|---|
app.use(middleware1)app.use(middleware2)next() | • Middleware executes sequentially in registration order • each can modify req/res and calls next() to pass control to the next layer in the chain | |
app.use((req, res, next) => { req.timestamp = Date.now() next()}) | • Defined directly in the pipeline using anonymous functions • good for prototyping but limits reusability across routes or apps | |
const logger = (opts) => { return (req, res, next) => {...}} | • Returns a configured middleware function • enables parameterization and reuse with different settings per route or application | |
class LoggerMiddleware { use(req, res, next) {...}} | • Middleware implemented as a class with lifecycle methods • common in TypeScript frameworks like NestJS for dependency injection support |