~3 min read • Updated Dec 26, 2025
1. What Is Middleware in Express?
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() or the request will hang.
2. A Simple Example
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000)
We will now add three middleware functions to this app.
3. Middleware Example: myLogger
This middleware logs a simple message for every request.
const myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
Load it using app.use():
app.use(myLogger)
Important notes:
- Middleware runs in the order it is loaded.
- If placed after a route handler, it may never run.
next()must be called to continue the chain.
4. Middleware Example: requestTime
This middleware adds a timestamp to the request object.
const requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
Usage:
app.use(requestTime)
app.get('/', (req, res) => {
res.send(`Requested at: ${req.requestTime}`)
})
5. Async Middleware Example: validateCookies
This middleware validates cookies using an external async service.
async function validateCookies (req, res, next) {
await cookieValidator(req.cookies)
next()
}
In Express 5, async middleware automatically triggers next(error) if it throws or rejects.
Usage with cookie-parser:
app.use(cookieParser())
app.use(validateCookies)
app.use((err, req, res, next) => {
res.status(400).send(err.message)
})
If you pass anything to next() (except 'route' or 'router'), Express treats it as an error.
6. Configurable Middleware
To create middleware that accepts options, export a function that returns the middleware implementation.
my-middleware.js
module.exports = function (options) {
return function (req, res, next) {
// Use options here
next()
}
}
Usage:
const mw = require('./my-middleware')
app.use(mw({ option1: '1', option2: '2' }))
Examples of configurable middleware: cookie-session, compression.
7. Key Takeaways
- Middleware executes in the order it is defined.
- If
next()is not called, the request will hang. - Async middleware automatically forwards errors.
- You can modify req and res freely.
- You can end the response or pass control onward.
- Middleware can be modular and configurable.
Conclusion
Middleware is the heart of Express.js. It enables logging, validation, error handling, request transformation, and modular architecture. With a solid understanding of middleware, you can build flexible, maintainable, and powerful Express applications.
Written & researched by Dr. Shahin Siami