Skip to main content
One idea at a time

Middleware order changes what a route can trust

Express connects an incoming request to a sequence of functions. Middleware can inspect the request, attach information, stop processing, or pass control to the next function.

This resembles composing frontend providers or interceptors, but order affects security and body interpretation. A task handler cannot trust a workspace scope before the middleware has authenticated the user and checked membership.

An illustrative request sequence is:

request identifier
body parsing and size limits
session authentication
CSRF check for an authenticated write
workspace membership and permission checks
input validation and task operation
error response handling

The exact wiring is visible in the application module. The sequence explains the dependencies rather than replacing the source.

Middleware can end the request​

An authentication check may return an error response when the session is missing or expired. That response ends processing. The task function must not continue afterward.

If middleware calls next(), Express continues to the next matching handler. Calling next() after sending a response can produce a second response attempt or unintended business work.

Express 5 forwards a rejected promise from an async handler to error handling. The application still needs a central error handler to map expected domain failures into its JSON error contract. Unexpected failures need a generic external message and a useful internal log.

Webhooks need their original body​

Stripe verifies a signature against the raw bytes it sent. Parsing JSON and serializing it again can change those bytes even when the values look identical.

The webhook route therefore needs raw-body handling before ordinary JSON parsing consumes that request. This is an example of ordering that has an observable consequence: a valid provider event can fail signature verification when body parsing is misplaced.

Normal task endpoints need parsed JSON with bounded body sizes. One parser does not fit every endpoint.

A common mistake is treating middleware as decoration around the important route code. Authentication, tenant scope, and signature checks decide what the route is allowed to do. Those checks are part of the behavior.

Why can an error handler hide implementation details?

It separates the internal exception and log from the external response. A database exception may contain information that the caller does not need and must not receive.

Read middleware in execution order. Each step must establish the facts that the following step relies on.

Read api/src/app.ts Read api/src/billing.ts