Middleware Order Matters
Express runs middleware top to bottom, so registration order controls behavior.
Express runs middleware in the order you register it. A middleware only affects routes defined after it. This is the most common source of confusion for beginners.
For example, body-parsing middleware must come before the routes that read req.body. Error-handling middleware must come last so it can catch everything before it.
Example
app.use(express.json()); // 1. parse JSON bodies first
app.get('/', (req, res) => { // 2. then routes
res.send('Home');
});
app.use((req, res) => { // 3. 404 fallback last
res.status(404).send('Not found');
});When to use it
- A logging middleware must be registered before authentication middleware to capture even rejected requests in the access log.
- A developer accidentally registers the JSON body parser after the route handler, causing req.body to be undefined, and fixes it by moving app.use(express.json()) above all routes.
- A catch-all 404 handler is always placed last so it only fires when no other route or middleware has sent a response.
More examples
Correct middleware order
Registers middleware in the correct order: log -> auth -> route -> 404 fallback.
const app = require('express')();
app.use((req, res, next) => { console.log('Step 1: log'); next(); });
app.use((req, res, next) => { req.user = { id: 42 }; next(); }); // Step 2: auth
app.get('/', (req, res) => res.json({ user: req.user })); // Step 3: route
app.use((req, res) => res.status(404).send('Not Found')); // Step 4: 404
app.listen(3000);Body parser must come before routes
Illustrates that the JSON body parser must be registered before any route that reads req.body.
const express = require('express');
const app = express();
// WRONG: route defined before the parser — req.body is undefined
// app.post('/data', (req, res) => res.json(req.body));
// app.use(express.json());
// CORRECT: parser first
app.use(express.json());
app.post('/data', (req, res) => res.json(req.body));
app.listen(3000);Early exit skips later middleware
Returns a response without calling next(), so the /data route handler is never reached for unauthenticated requests.
app.use((req, res, next) => {
if (!req.headers['x-api-key']) {
return res.status(401).json({ error: 'Missing key' }); // stops here
}
next(); // only called when key is present
});
app.get('/data', (req, res) => res.send('Secure data'));
Discussion