~3 min read • Updated Dec 26, 2025
1. What Is Middleware?
A middleware function in Express has access to:
- req – the request object
- res – the response object
- next – a function that passes control to the next middleware
Middleware can:
- Execute any code
- Modify req or res
- End the request–response cycle
- Call
next()to continue the chain
If a middleware does not end the response, it must call next(), otherwise the request will hang.
2. Types of Middleware in Express
- Application-level middleware
- Router-level middleware
- Error-handling middleware
- Built-in middleware
- Third-party middleware
3. Application-Level Middleware
3.1 Middleware Without a Mount Path
app.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
3.2 Middleware With a Mount Path
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
3.3 Route Handler as Middleware
app.get('/user/:id', (req, res) => {
res.send('USER')
})
3.4 Middleware Sub-stack
app.use('/user/:id',
(req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
},
(req, res, next) => {
console.log('Request Type:', req.method)
next()
}
)
4. Multiple Routes for the Same Path
app.get('/user/:id', (req, res, next) => {
console.log('ID:', req.params.id)
next()
}, (req, res) => {
res.send('User Info')
})
app.get('/user/:id', (req, res) => {
res.send(req.params.id)
})
The second route never runs because the first one ends the response.
5. Skipping Middleware with next('route')
app.get('/user/:id', (req, res, next) => {
if (req.params.id === '0') next('route')
else next()
}, (req, res) => {
res.send('regular')
})
app.get('/user/:id', (req, res) => {
res.send('special')
})
next('route') only works inside app.METHOD() or router.METHOD().
6. Middleware as an Array
function logOriginalUrl(req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod(req, res, next) {
console.log('Request Type:', req.method)
next()
}
const logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, (req, res) => {
res.send('User Info')
})
7. Router-Level Middleware
Works like application-level middleware but is attached to a Router instance:
const router = express.Router()
router.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
router.use('/user/:id',
(req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
},
(req, res, next) => {
console.log('Request Type:', req.method)
next()
}
)
router.get('/user/:id', (req, res, next) => {
if (req.params.id === '0') next('route')
else next()
}, (req, res) => {
res.render('regular')
})
router.get('/user/:id', (req, res) => {
res.render('special')
})
app.use('/', router)
Skipping Router Middleware with next('router')
router.use((req, res, next) => {
if (!req.headers['x-auth']) return next('router')
next()
})
8. Error-Handling Middleware
Error-handling middleware must have four arguments:
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
9. Built-in Middleware
- express.static – serves static files
- express.json – parses JSON bodies
- express.urlencoded – parses URL-encoded bodies
10. Third-Party Middleware
Example: cookie-parser
npm install cookie-parser
const cookieParser = require('cookie-parser')
app.use(cookieParser())
Conclusion
Middleware is the backbone of Express.js. It controls the flow of requests, enables validation, logging, error handling, and modular architecture. Mastering middleware means mastering Express itself.
Written & researched by Dr. Shahin Siami