[Docs] Add comprehensive middleware execution order and error handling examples
Description
Issue Description
The current Express.js documentation covers middleware basics, but lacks comprehensive examples demonstrating:
- Middleware execution order with multiple middleware functions
- Error-handling middleware best practices and common patterns
- Async/await middleware with proper error propagation
- Router-level vs application-level middleware interactions
- Built-in middleware execution timing and order
Current State
The existing docs at https://expressjs.com/en/guide/using-middleware.html provide basic examples, but developers (especially beginners) often struggle with:
- Understanding when
next()should be called - How error-handling middleware differs from regular middleware
- Execution order when combining app.use(), router.use(), and route-specific middleware
- Common mistakes that lead to hanging requests or uncaught errors
Proposed Improvement
Add a dedicated section or expand the existing middleware guide with:
1. Visual Execution Flow Diagram
Show the order of execution with a clear diagram or flowchart
2. Complete Working Examples
// Example: Middleware execution order
const express = require('express');
const app = express();
// Application-level middleware
app.use((req, res, next) => {
console.log('1. App-level middleware');
next();
});
// Router with its own middleware
const router = express.Router();
router.use((req, res, next) => {
console.log('2. Router-level middleware');
next();
});
router.get('/api/users',
(req, res, next) => {
console.log('3. Route-specific middleware');
next();
},
(req, res) => {
console.log('4. Final route handler');
res.json({ users: [] });
}
);
app.use('/api', router);
// Error-handling middleware (must be last)
app.use((err, req, res, next) => {
console.error('5. Error handler:', err);
res.status(500).json({ error: err.message });
});
3. Common Patterns Section
- Authentication middleware
- Request validation
- Async error handling wrapper
- Response time logging
4. Troubleshooting Guide
- "Request hangs" → forgot to call next() or send response
- "Error not caught" → error handler not defined or placed incorrectly
- "Middleware skipped" → route matched before middleware executed
Benefits
- Reduces support questions and Stack Overflow posts about middleware
- Helps developers avoid common pitfalls
- Provides copy-paste ready examples for common use cases
- Improves onboarding for new Express users
Related
This complements issue #6917 about async/await error handling best practices.
Expectations
The updated documentation should include:
- A dedicated page or expanded section on middleware execution order
- Interactive examples showing console output to visualize execution flow
- Side-by-side comparison of correct vs incorrect patterns
- Clear warnings about common mistakes (e.g., placing error handlers before routes)
- Best practices for structuring middleware in larger applications
Developers should be able to:
- Understand middleware execution order without trial and error
- Copy working examples for authentication, logging, and error handling
- Debug middleware-related issues using the troubleshooting guide
- Confidently build applications with complex middleware chains
The documentation is maintained in expressjs/expressjs.com, so this issue should be moved there, but let me answer some of your problems:
Execution order and next()
- Middleware execution order with multiple middleware functions
- Understanding when
next()should be called
To me the examples in Using Express middleware show that the middleware is executed in the same order that it is declared. All types of middleware from your example are documented. There is also information when next() should be called and how next('route') and next('router') can skip some middleware.
- Router-level vs application-level middleware interactions
- Execution order when combining app.use(), router.use(), and route-specific middleware
This could maybe be somehow improved. I don't think it is explicitly written that the order is "app middleware until router" -> "router middleware until route" -> "route middleware". It shouldn't be unexpected for most people, but stating it in the docs could be helpful for someone.
Error handling
- Error-handling middleware best practices and common patterns
- How error-handling middleware differs from regular middleware
There is a separate guide Express error handling which describes this, including among other things the differences in signature (also in Using middleware guide) and that it should be defined last.
Promises, async/await and error handling
- Async/await middleware with proper error propagation
This is also described in the Express error handling guide.
And by the way there is no need for async error handling wrappers - rejected Promises are caught and call next(value) (see the guide).
Built-in middleware
- Built-in middleware execution timing and order
What do you mean by this? It's normal middleware that is executed in the same way as everything else. It doesn't get magically executed at random time. You should think of it as of third-party middleware that is a re-exported dependency of Express.
Common mistakes
- Common mistakes that lead to hanging requests or uncaught errors
There is no separate section for this, but there is an information that next() should be called or the request will be left hanging and that error handling middleware should be defined last (possible cause of uncaught errors).
Common patterns
Some of this is described in the Writing middleware for use in Express guide, FAQ and maybe examples:
- auth: https://github.com/expressjs/express/tree/master/examples/auth
- request validation: I'm not sure what exactly do you mean by that, but there is a cookie validation middleware example in Writing middleware guide
- async: see the section about async - no wrappers are necessary, it just works (in Express 5)
- response time logging - it is a section in Writing middleware guide