What are the different types of middleware in Express.js?
Types of Middleware in Express.js
Middleware functions are the backbone of Express.js. They have access to the req, res, and next objects. Express has five distinct types of middleware.
1. Application-level Middleware
Bound to the app object using app.use() or app.METHOD():
const express = require('express');
const app = express();
// Runs on EVERY request
app.use((req, res, next) => {
console.log(`${req.method} ${req.url} - ${Date.now()}`);
next();
});
// Runs only for GET /users
app.get('/users', (req, res, next) => {
// ...
next();
});2. Router-level Middleware
Bound to a Router instance — works identically to application-level but scoped to a router:
const router = express.Router();
// Runs on every request to this router
router.use((req, res, next) => {
console.log('Router middleware');
next();
});
router.get('/profile', (req, res) => {
res.json({ user: 'John' });
});
app.use('/api/users', router);
// Middleware runs on: GET /api/users/profile3. Error-handling Middleware
Has four parameters — Express recognizes it by the signature (err, req, res, next):
// Must have exactly 4 parameters!
app.use((err, req, res, next) => {
console.error(err.stack);
if (err.name === 'ValidationError') {
return res.status(400).json({ error: err.message });
}
if (err.name === 'UnauthorizedError') {
return res.status(401).json({ error: 'Unauthorized' });
}
res.status(500).json({ error: 'Internal Server Error' });
});Error middleware must be defined last, after all routes:
// Routes first
app.use('/api/users', userRoutes);
app.use('/api/products', productRoutes);
// Then error handler
app.use(errorHandler);4. Built-in Middleware
Express has three built-in middleware functions:
// Parse JSON bodies
app.use(express.json());
// Parse URL-encoded bodies
app.use(express.urlencoded({ extended: true }));
// Serve static files
app.use(express.static('public'));5. Third-party Middleware
Installed via npm:
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const compression = require('compression');
app.use(cors()); // CORS headers
app.use(helmet()); // Security headers
app.use(morgan('dev')); // HTTP request logging
app.use(compression()); // Gzip compressionMiddleware Execution Order
Middleware executes in the order it's defined:
app.use(cors()); // 1st
app.use(helmet()); // 2nd
app.use(express.json()); // 3rd
app.use(morgan('dev')); // 4th
app.use('/api', routes); // 5th — route handlers
app.use(notFoundHandler); // 6th — 404 handler
app.use(errorHandler); // 7th — error handler (LAST)Important Rules
| Rule | Description |
|---|---|
Always call next() | Or the request hangs |
Don't call next() after res.send() | Causes "headers already sent" error |
| Error handler = 4 params | Must have (err, req, res, next) |
| Order matters | Define middleware before routes |
Use next(err) to pass errors | Skips to error-handling middleware |
// Passing errors to error handler
app.get('/api/users/:id', async (req, res, next) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
const err = new Error('User not found');
err.status = 404;
return next(err); // Skip to error handler
}
res.json(user);
} catch (err) {
next(err); // Passes to error handler
}
});Tip: Think of middleware as a pipeline. Each function either handles the request, passes it to the next function with
next(), or short-circuits withnext(err).
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.