awesome-everything RU
↑ Back to the climb

Backend Architecture

Routing and middleware: choosing what runs, and in what order

Crux Routing maps one request to one handler; the middleware chain decides what runs around it. Order is not cosmetic — it determines whether auth, body limits, and compression actually protect you.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at middle altitude — in the sky
◷ 13 min

A security review finds that one admin endpoint accepts unauthenticated requests. The auth middleware exists, it is well-tested, and it is applied — but it was registered after the route in question. The handler ran first. Nobody wrote a bug; someone wrote the lines in the wrong order.

Routing: matching a path to a handler

Routing turns POST /users/42/orders into a single handler plus extracted params (userId=42). How it matches determines its cost:

  • Linear scan — try each registered route in order. Simple, but O(n) in route count; fine for dozens of routes.
  • Radix trie (httprouter, Echo, Fastify’s find-my-way) — a prefix tree over path segments. O(length of path), independent of route count, so 10 routes and 10,000 routes match in the same time.

In practice routing is microseconds either way; it almost never dominates latency. The real routing bugs are correctness: overlapping patterns (/users/:id vs /users/me), trailing-slash mismatches, and method confusion (a GET route shadowing a POST on the same path).

Middleware: the chain around the handler

Middleware are functions that run before and/or after the handler, each able to read the request, modify it, short-circuit it, or pass control onward. They handle cross-cutting concerns — things every endpoint needs but no endpoint should re-implement: authentication, request logging, body parsing, rate limiting, compression, error handling.

The model is an onion. A request travels inward through each layer to the handler, then the response travels outward through the same layers in reverse:

request →  logging → auth → bodyParser → handler
response ← logging ← auth ← bodyParser ← handler

A layer that calls next() passes control inward. A layer that responds without calling next() short-circuits — the handler never runs. That is exactly how a rate limiter returns 429 or an auth layer returns 401 before any business logic executes.

Order is a security boundary

Because each layer can short-circuit, the order of registration decides what actually protects the handler:

Wrong orderConsequence
Route registered before auth middlewareHandler runs unauthenticated
Body parser before a body-size limitServer buffers a 2 GB upload before rejecting it
Compression before authCompressed error responses leak; CPU spent on requests that 401
Error handler registered firstIt never catches anything — errors propagate past it
Rate limiter after expensive workYou do the work, then decline to charge for it

The rule that prevents all five: cheap and protective layers go first (size limits, rate limits, auth), expensive and optional layers go last (body parsing, compression), and the error handler goes outermost so it wraps everything.

Where time actually goes

Middleware is also where invisible latency accumulates. Each layer runs on every request. A body parser that JSON-parses a 1 MB payload, a logging layer that does a synchronous DNS lookup, an auth layer that calls a remote token service without caching — these add milliseconds to every request, not just the slow ones. Profiling a slow endpoint means timing the chain, not just the handler.

Quiz

An admin endpoint is reachable without authentication, even though auth middleware is implemented and tested. What is the most likely cause?

Quiz

Why place a request-size limit BEFORE the body parser in the middleware chain?

Order the steps

Order a sound middleware chain from outermost (runs first) to the handler:

  1. 1 Error handler wraps everything (catches downstream throws)
  2. 2 Request logging / tracing (assign a request ID)
  3. 3 Rate limiting (short-circuit 429 before doing work)
  4. 4 Authentication (short-circuit 401 before the handler)
  5. 5 Body size limit, then body parsing
  6. 6 Handler (business logic)
Recall before you leave
  1. 01
    How does a radix-trie router differ from a linear-scan router, and does routing usually dominate latency?
  2. 02
    Explain the onion model of middleware and what 'short-circuiting' means.
  3. 03
    Why is middleware order a security boundary, and what is the ordering rule?
Recap

With a parsed request in hand, the server chooses what code runs. Routing matches the method and path to exactly one handler; a radix trie keeps match time independent of route count, but the routing bugs that bite are correctness ones — overlapping patterns and method confusion. Around the handler sits the middleware chain, an onion of cross-cutting layers (auth, logging, body parsing, rate limiting, compression, error handling) where any layer can short-circuit the request. That power makes registration order a security and performance boundary: protective cheap layers first, expensive optional layers last, error handler outermost. Middleware is also where per-request latency quietly accumulates. The next stop is the center of the onion: the handler itself and turning its result into a response.

Connected lessons
appears again in185
Continue the climb ↑Handler and response: from business logic to bytes on the wire
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.