npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@evanion/nestjs-correlation-id

v2.0.0

Published

Correlation ID middleware for NestJS. Propagates a request-scoped correlation id across incoming requests, outgoing HTTP calls and logs.

Downloads

1,501

Readme

Requirements

| | | | ---------- | ----------- | | NestJS | 12 | | Node | 20 or newer |

Ships ESM only, matching NestJS 12. There is no CommonJS build, so require('@evanion/nestjs-correlation-id') will not work — use import.

One build means one module graph and one CorrelationService class object, so injecting by class token is always safe. The dual build this package used to ship could hand Nest two unrelated copies of the same class.

The middleware is typed against node:http's IncomingMessage and ServerResponse and reads and writes raw headers, so it works under @nestjs/platform-express and @nestjs/platform-fastify alike. express is not a peer dependency.

@nestjs/axios is an optional peer dependency, needed only if you use withCorrelation. It is a type-only import, so it is not pulled in at runtime.

This package has no runtime dependencies beyond tslib.

Why?

When debugging an issue in your applications logs, it helps to be able to follow a specific request up and down your whole stack. This is usually done by including a correlation-id (aka Request-id) header in all your requests, and forwarding the same id across all your microservices.

Installation

yarn add @evanion/nestjs-correlation-id
npm install @evanion/nestjs-correlation-id

How to use

Add the middleware to your AppModule

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import {
  CorrelationIdMiddleware,
  CorrelationModule,
} from '@evanion/nestjs-correlation-id';

@Module({
  imports: [CorrelationModule.forRoot()],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(CorrelationIdMiddleware).forRoutes('*');
  }
}

CorrelationIdMiddleware opens an AsyncLocalStorage context for the request. Everything downstream of it — guards, interceptors, controllers, and anything they await — sees that request's id, and concurrent requests stay isolated.

Then forward the id on outgoing HTTP calls by passing withCorrelation() to HttpModule.registerAsync.

import { HttpModule } from '@nestjs/axios';
import { withCorrelation } from '@evanion/nestjs-correlation-id';

@Module({
  imports: [HttpModule.registerAsync(withCorrelation())],
  controllers: [UsersController],
  providers: [UsersService],
})
export class UsersModule {}

Use HttpService as usual in UsersService and UsersController. It stays a singleton: the correlation header is attached by an axios request interceptor that reads the current context when the request is made.

withCorrelation() needs CorrelationModule.forRoot() to have been called somewhere in the application — it is a global module, so once in the root module is enough. Without it, Nest fails at boot with Nest can't resolve dependencies of the HTTP_MODULE_OPTIONS (?).

Working outside a request

CorrelationService is a singleton, so it is injected like any other provider and resolved with module.get(CorrelationService). Outside a correlation context getCorrelationId() returns undefined, and outgoing calls carry no correlation header.

For work with no request behind it — queue consumers, cron jobs, scripts — open a context yourself:

await this.correlationService.run(this.correlationService.generate(), () =>
  this.processJob(job),
);

Configuration

CorrelationModule.forRoot() accepts a CorrelationConfig, exported from the package root.

import {
  CorrelationModule,
  type CorrelationConfig,
} from '@evanion/nestjs-correlation-id';

const config: Partial<CorrelationConfig> = {
  header: 'X-Request-Id', // defaults to 'X-Correlation-Id'
  generator: () => myId(), // defaults to node:crypto randomUUID
};

CorrelationModule.forRoot(config);

Customize

You can easily customize the header and ID by including a config when you register the module

@Module({
  imports: [CorrelationModule.forRoot({
    header: string
    generator: () => string
  })]
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(CorrelationIdMiddleware).forRoutes('*');
  }
}

Add correlationId to logs

Inject CorrelationService wherever you build log context and read the current id. It is a singleton, so nothing about injecting it changes the scope of the provider holding it.

import { CorrelationService } from '@evanion/nestjs-correlation-id';
import { Injectable, NestMiddleware } from '@nestjs/common';
import type { IncomingMessage, ServerResponse } from 'node:http';
import * as Sentry from '@sentry/node';

@Injectable()
export class SentryTagMiddleware implements NestMiddleware {
  constructor(private readonly correlationService: CorrelationService) {}

  use(_req: IncomingMessage, _res: ServerResponse, next: () => void) {
    const correlationId = this.correlationService.getCorrelationId();
    if (correlationId) Sentry.setTag('correlationId', correlationId);
    next();
  }
}

getCorrelationId() is synchronous — it never returned a promise — and gives undefined when there is no correlation context, so apply this after CorrelationIdMiddleware, which is what opens one.

@Module({
  imports: [CorrelationModule.forRoot()],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(CorrelationIdMiddleware).forRoutes('*');
    consumer.apply(SentryTagMiddleware).forRoutes('*');
  }
}

To replace the id of the current context:

this.correlationService.setCorrelationId('some_correlation_id');

It throws outside a correlation context, rather than writing somewhere nothing will read.

See the specs on GitHub for fully worked examples, including an end-to-end one that stands up a real Nest application.

Change Log

See Changelog for more information.

Contributing

Contributions welcome! See Contributing.

Author

Mikael Pettersson (Evanion on Discord)

License

Licensed under the MIT License - see the LICENSE file for details.