Run Code Before the Route Handler
Middleware
Middleware is the Express-style hook in Nest. It runs first, can mutate req/res, and must call next() to pass control along.
What you'll learn
- Write a class- or function-style middleware
- Apply middleware via configure() in a module
- Scope it to routes, methods, or wildcards
Middleware sits at the bottom of Nest’s request pipeline — it’s the first thing to see an incoming request and runs before guards, pipes, or interceptors. If you’ve written Express middleware, you already know the shape.
A Class Middleware
Class middleware integrates with DI, so it can inject services.
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const start = Date.now();
res.on('finish', () => {
console.log(`${req.method} ${req.url} ${res.statusCode} +${Date.now() - start}ms`);
});
next();
}
} Applying It
Middleware is registered inside a module’s configure hook, not via a
decorator. That lets you scope it precisely.
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*'); // every route in this module
}
} The argument to forRoutes can be a string path, a controller class, or an
object with path + method for surgical scoping.
configure(consumer: MiddlewareConsumer) {
consumer
.apply(AuthMiddleware)
.exclude(
{ path: 'users/health', method: RequestMethod.GET },
)
.forRoutes(UsersController);
} Functional Middleware
If your middleware has no dependencies, skip the class altogether — Nest accepts plain functions too.
import { Request, Response, NextFunction } from 'express';
export function requestId(req: Request, _res: Response, next: NextFunction) {
(req as any).id = crypto.randomUUID();
next();
}
// Module
configure(consumer: MiddlewareConsumer) {
consumer.apply(requestId).forRoutes('*');
} Where Middleware Fits
Middleware is the first layer Nest runs on a request. The order is:
middleware → guards → interceptors (pre) → pipes → handler →
interceptors (post) → exception filters That order matters: middleware can’t read decorator metadata yet (no
ExecutionContext), and it can’t easily short-circuit a route with a
typed exception response — guards and filters are better for that. Use
middleware for the things Express historically handled: logging, body
parsing tweaks, request IDs, low-level CORS.