Ahead of the release
npm install @evanion/nestjs-correlation-id gives you 2.0.0. These pages document main, which has changes that release does not.
@evanion/nestjs-correlation-id
A correlation id on every request, carried through everything the request awaits, and forwarded on outgoing HTTP calls.
@Module({
imports: [CorrelationModule.forRoot()],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(CorrelationIdMiddleware).forRoutes('*');
}
}The id comes from a header the caller sends — X-Correlation-Id by default, or
whichever one you configure — reused where it arrives, minted where it does not,
and forwarded to everything downstream, so a log line in one service can be
matched to the request that produced it in another.
Installation
npm install @evanion/nestjs-correlation-id| NestJS | ^12.0.0 |
| Node | 20 or newer |
@nestjs/axios | ^12.0.0, optional — only for withCorrelation() |
ESM only, matching NestJS 12. There is no CommonJS build, so
require('@evanion/nestjs-correlation-id') will not work. No runtime
dependencies beyond tslib.
One build means one module graph and one CorrelationService class object, so
injecting by class token is always safe. A dual build can hand Nest two
unrelated copies of the same class, and then an injection that looks correct
resolves nothing.
How the pieces fit
| Export | What it does |
|---|---|
CorrelationModule | provides the service and the resolved configuration, globally |
CorrelationIdMiddleware | opens the correlation context around each request |
CorrelationService | reads, replaces and mints the id |
withCorrelation() | HttpModule.registerAsync options that forward the id |
The context is an
AsyncLocalStorage, not a
request-scoped provider. Request-scoping CorrelationService would propagate
upward through the injection graph: every provider that depends on it —
including HttpService, via withCorrelation — would become request-scoped
too, re-instantiated per request and never given onModuleInit.
Everything downstream of the middleware sees its request’s id, and concurrent requests stay isolated.
Adapter-agnostic
The middleware is typed against node:http’s IncomingMessage and
ServerResponse and only reads and writes raw headers, so it works under
@nestjs/platform-express and @nestjs/platform-fastify alike. express is not
a peer dependency.
Pages
- Getting started — the middleware, outgoing calls, work with no request
- Configuration — header, generator, and the validator
- API reference