Middleware Pattern
A pattern where request processing is composed as a chain of functions, each of which can inspect, transform, or short-circuit the request before passing it to the next handler.
Description
The Middleware pattern structures request processing as a pipeline of composable functions, where each middleware in the chain can inspect the incoming request, modify it, short-circuit processing (e.g., return an error response), or pass control to the next middleware via a next() call. This pattern is the backbone of web frameworks like Express, Koa, Fastify, and Hono, where middleware handles cross-cutting concerns—authentication, logging, CORS, rate limiting, body parsing, error handling—without coupling them to business logic.
Middleware follows the Chain of Responsibility design pattern: each handler decides whether to process the request or delegate to the next handler. The power lies in composability—middleware can be added, removed, or reordered without modifying other middleware or route handlers. The pattern extends beyond HTTP: Redux middleware intercepts dispatched actions for logging, async operations, and analytics; React's middleware-like patterns include higher-order components and context providers; and build tools like webpack use loader chains that are essentially middleware for file transformations.
Effective middleware design requires clear ordering conventions (authentication before authorization before validation before handler), proper error propagation (try-catch wrapping or error-handling middleware registered last), and performance awareness (heavy middleware like body parsing should be applied only to routes that need it, not globally). The middleware pattern also enables aspect-oriented programming: you can add logging, metrics, or circuit breaking to every endpoint without modifying any endpoint. The anti-pattern is middleware that does too much—each middleware should have a single responsibility.
Prompt Snippet
Structure the Hono middleware pipeline with explicit ordering: 1) requestId middleware that generates a UUID and sets it on c.set('requestId'), 2) structured logger middleware using pino that logs method, path, status, and duration with the request ID, 3) CORS middleware configured per-route group, 4) rate limiter using a sliding window counter in Redis keyed by IP + endpoint, 5) auth middleware that validates the JWT via jose, extracts claims, and sets c.set('user'), 6) Zod validation middleware factory that validates body/params/query against route-specific schemas. Register a global onError handler that maps domain errors (NotFoundError, ValidationError, AuthorizationError) to appropriate HTTP status codes and structured error responses. Apply body-parsing middleware only to POST/PUT/PATCH routes to avoid overhead on GET endpoints.Tags
Related Terms
Redux / Global State Patterns
A predictable state container pattern where all application state lives in a single store, updated exclusively through dispatched actions processed by pure reducer functions.
Strategy Pattern
A behavioral design pattern that defines a family of interchangeable algorithms, encapsulates each one, and allows the algorithm to be selected at runtime.
Service Layer Pattern
An architectural layer that defines the application's boundary and coordinates domain logic, transaction management, and cross-cutting concerns through service classes.
Dependency Injection
A design pattern where objects receive their dependencies from an external source rather than creating them internally, enabling loose coupling and testability.