Skip to Content
Correlation IDOverview

Unreleased changes

These pages document main, which has changes 2.1.1 does not. npm install @evanion/nestjs-correlation-id gives you 2.1.1, documented here. Values on these pages are produced by running the current source on every build.

@evanion/nestjs-correlation-id

To follow one order through Baize, the board game shop these pages use, you search the logs of storefront, orders and stock. @evanion/nestjs-correlation-id gives each request one id that every NestJS service it reaches puts in its own log lines.

How one correlation id crosses services

In @evanion/nestjs-correlation-id, a correlation id is a string that names one request in every service the request reaches. CorrelationService is the provider that holds the current id, in Node’s AsyncLocalStorage.

A correlation context is the scope that CorrelationService.run(id, callback) opens: the callback and everything it calls or awaits. Inside that scope, the service’s getCorrelationId() method returns id.

The code below opens two contexts by hand, with a different id in each, and runs one handler in both at once. The handler awaits and then reads the id, and each run gets its own context’s id back:

import { } from '@evanion/nestjs-correlation-id'; // In an application Nest builds the service, and you inject it. Built by hand // it takes a configuration object. The service calls only its generator, and // the header is there because the configuration's type requires one. const = new ({ : 'X-Correlation-Id', : () => .(), }); // A handler that awaits before it reads the id, as a database call would. const = async () => { await new (() => (, 5)); return .(); }; const [, ] = await .([ .('storefront-4f1c9a', ), .('storefront-9d2e71', ), ]); ; // -> 'storefront-4f1c9a' ; // -> 'storefront-9d2e71' .(); // -> undefined

Outside both contexts getCorrelationId() returns undefined, because no context is open there. In an application CorrelationIdMiddleware opens the context for each request, so a handler only reads the id.

CorrelationIdMiddleware reads the id from the X-Correlation-Id header and reuses it when it passes a format check. When the header is missing or fails the check, the middleware generates a new id. It sets the same header on the response.

A hop is one call from a service to the next, such as orders asking stock for a game’s stock level. withCorrelation() configures HttpModule from @nestjs/axios so that every hop through HttpService carries the id, and the next service’s middleware reuses it:

One X-Correlation-Id header carried from storefront through orders to stock.

What nestjs-correlation-id provides

Every application uses these @evanion/nestjs-correlation-id exports:

ExportWhat it does
CorrelationModuleprovides CorrelationService and its configuration (header, generator, format check) to every module
CorrelationIdMiddlewareopens a correlation context per request and sets the id on the response
CorrelationServicereads and generates the id, and opens a context for work with no request
withCorrelation()HttpModule.registerAsync options that send the id on every call
DEFAULT_CORRELATION_ID_VALIDATORthe format check an incoming header passes before the middleware reuses it

A queue consumer or a cron job has no request behind it, so it opens its own context with CorrelationService.run().

What nestjs-correlation-id leaves to you

@evanion/nestjs-correlation-id carries the id and stops there:

  • It writes no log line. Your logger injects CorrelationService, calls getCorrelationId() and adds the value to its own output.
  • It reads one header, X-Correlation-Id unless you configure another. There is no list of fallback header names.
  • It forwards the id on HttpService calls whose module used withCorrelation(). A fetch call or a queue message carries the id only when your code puts it there.
  • It records no spans and no timings. A tracer such as OpenTelemetry does that, and can run beside it.

Put an id on every request

You have seen @evanion/nestjs-correlation-id carry one id through awaits and across a hop. Getting started installs it, registers CorrelationModule and CorrelationIdMiddleware in your application, and has a handler read the id a caller sent.

Last updated on