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

@vizydrop/correlation-id

v7.0.1

Published

Vizydrop correlation id helper based on async hooks

Readme

Correlation Id

Correlation ID propagation across async contexts using AsyncLocalStorage. Provides middleware for Express/Koa and enhancers for HTTP clients (got, request, http-proxy) to automatically attach correlation IDs and baggage headers to all outbound requests.

Written in TypeScript (versions > 6.0).

Installation

yarn add @vizydrop/correlation-id

How to use

Create correlation id instance

const {createCorrelationId} = require('@vizydrop/correlation-id');
const correlationId = createCorrelationId();

Integrate with @vizydrop/logger

const {createLogger} = require(`@vizydrop/logger`);

const logger = createLogger({
    correlationId: {
        enabled: true,
        getCorrelationId: () => correlationId.correlator.getId(),
        emptyValue: 'nocorrelation',
    },
    baggage: {
        enabled: true,
        getBaggage: () => correlationId.correlator.getParsedBaggage(),
    },
});

Register middleware

Support for koa and express:

// express
app.use(correlationId.expressMiddleware);

// koa
app.use(correlationId.koaMiddleware);

Enhance got

Each request will automatically contain the correlation ID and baggage headers:

import got from 'got';

const correlatedGot = correlationId.enhanceGot(got);
correlatedGot.get('http://anotherservice:10020/data');

Enhance request

const request = require('request');
const correlatedRequest = correlationId.enhanceRequest(request);
correlatedRequest.get('http://anotherservice:10020/data');

Enhance axios

axios has no way to derive a new instance that inherits interceptors, so the instance is mutated in place and returned. Prefer a dedicated instance over the shared default export:

import axios from 'axios';

const http = correlationId.enhanceAxios(axios.create());
http.get('http://anotherservice:10020/data');

In NestJS, enhance the axios instance behind HttpService:

@Injectable()
export class HttpCorrelation implements OnModuleInit {
    constructor(private readonly http: HttpService) {}

    onModuleInit(): void {
        correlationId.enhanceAxios(this.http.axiosRef);
    }
}

Enhance http-proxy

Each proxied request will contain the correlation ID and baggage headers:

import httpProxy from 'http-proxy';

const proxy = httpProxy.createProxyServer({target: 'http://anotherservice:10020/'});
correlationId.enhanceHttpProxy(proxy);

Run background jobs

Jobs usually do not go through express/koa middleware so correlation ID should be generated manually:

function jobTask() { /* ... */ }

function runJob() {
    correlationId.correlator.withId(correlationId.correlator.generateId(), () => {
        jobTask();
    });
}

Framework compatibility

The package declares no framework dependencies. Request, response, proxy and HTTP client types are described structurally, so the same build works with:

| Library | Verified versions | |---------|-------------------| | express | 4.x and 5.x | | koa | 2.x and 3.x | | got | 11.x (CommonJS) through 16.x (ESM) | | axios | 1.x (including @nestjs/axios HttpService.axiosRef) | | request | 2.48.x | | http-proxy | 1.18.x | | @nestjs/platform-express | 11.x (both app.use() and a NestMiddleware wrapper) |

The only runtime dependencies are @opentelemetry/api and @opentelemetry/core. Correlation IDs are generated with Node's built-in crypto.randomUUID(), so no uuid peer dependency is required.

How the table is verified

Two majors of one package cannot be installed under a single name, so the older ones come from aliased devDependencies (express4, types-express4, types-koa2, got11):

| Check | What it covers | |-------|----------------| | yarn test:types | compiles test/types/current-majors.test-d.ts against the current majors — express 5, koa 3, got 16, axios 1, http-proxy 1.18 | | yarn test:compat | compiles the same src against the previous majors — @types/express 4, @types/koa 2, got 11 — through test/compat/legacy-majors.ts. This is also the only check that resolves the package the way a CommonJS consumer does | | yarn test | runtime integration against real servers and clients in test/integration/: express 4 and 5, koa 3, fastify 5, got 11 and 16, axios 1, http-proxy |

NestJS

@Injectable()
export class CorrelationMiddleware implements NestMiddleware {
    use(req: Request, res: Response, next: NextFunction): void {
        correlationId.expressMiddleware(req, res, next);
    }
}

Fastify

There is no dedicated Fastify middleware — the correlator is used directly from an onRequest hook, and the context survives into route handlers:

app.addHook('onRequest', (req, reply, done) => {
    correlationId.correlator.withId(req.headers['x-correlationid'] as string | undefined, () => {
        const id = correlationId.correlator.getId();
        if (id) reply.header('x-correlationid', id);
        const inbound = req.headers.baggage as string | undefined;
        if (inbound) correlationId.correlator.setBaggage(inbound);
        done();
    });
});

Baggage Propagation

Baggage allows attaching key-value metadata to a request context and propagating it across services via the Baggage HTTP header (W3C standard).

Automatic propagation

Both Express and Koa middleware propagate inbound Baggage headers — if a request arrives with a Baggage header, it is captured and forwarded on outbound requests (via enhanceGot, enhanceRequest, enhanceHttpProxy).

However, only the Express middleware supports creating baggage from request data via the extractBaggage callback. Koa middleware only forwards existing baggage headers.

Custom baggage extraction (Express only)

Extract baggage from request data (e.g. JWT tokens, custom headers). Note that when extractBaggage is provided it replaces inbound baggage handling — the incoming Baggage header is not merged into the result, and if every extracted value is falsy (null, undefined, '', 0) no baggage is set at all, including the inbound one:

const correlationId = createCorrelationId({
    extractBaggage: (req) => ({
        userId: req.headers['x-user-id'],
        accountId: req.headers['x-account-id'],
    }),
});

To access framework-specific request properties, widen the request type:

import type {Request} from 'express';

const correlationId = createCorrelationId<Request>({
    extractBaggage: (req) => ({userId: req.user?.id, path: req.path}),
});

W3C size limits

Baggage is serialized through OpenTelemetry's W3CBaggagePropagator, which enforces the limits from the W3C specification. Values that exceed them are dropped rather than truncated:

| Limit | Behaviour when exceeded | |-------|-------------------------| | 4096 characters per key=value pair | that entry is dropped; if it was the only entry, no Baggage header is sent | | 180 entries | entries past the 180th are dropped | | 8192 characters in total | the header is cut off at the limit |

Keep baggage small — it travels with every outbound request.

Manual baggage management

correlationId.correlator.withId('my-id', () => {
    // Set baggage
    correlationId.correlator.setBaggage('key1=value1,key2=value2');

    // Get raw baggage string
    correlationId.correlator.getBaggage(); // 'key1=value1,key2=value2'

    // Get parsed baggage as object
    correlationId.correlator.getParsedBaggage(); // {key1: 'value1', key2: 'value2'}
});

Custom baggage header name

const correlationId = createCorrelationId({
    baggageHeaderName: 'x-custom-baggage',
});

Settings

Custom settings can be passed as an object to createCorrelationId:

| Option | Type | Default | Description | |--------|------|---------|-------------| | generateDefaultId | () => string | crypto.randomUUID() | Function that returns a new correlation ID | | httpHeaderParamName | string | 'x-correlationid' | HTTP header name for correlation ID | | baggageHeaderName | string | 'Baggage' | HTTP header name for baggage propagation | | extractBaggage | (req) => Record \| null | — | Custom function to extract baggage from request |

API Reference

createCorrelationId(opts?)

Returns a CorrelationIdApi object with:

| Property | Description | |----------|-------------| | correlator | Core correlator instance | | expressMiddleware | Express middleware | | koaMiddleware | Koa middleware | | enhanceGot(got) | Returns enhanced got instance with correlation headers | | enhanceAxios(instance) | Registers a request interceptor that adds correlation headers, returns the same instance | | enhanceRequest(request) | Returns enhanced request instance with correlation headers | | enhanceHttpProxy(proxy) | Registers proxyReq listener that adds correlation headers |

correlator

| Method | Description | |--------|-------------| | getId() | Returns current correlation ID (or undefined outside context) | | withId(id, fn) | Run function within a correlation ID context | | withIdAndReturn(id, fn) | Same as withId but returns the function's return value | | generateId() | Generate a new correlation ID | | setBaggage(value) | Set baggage string for current context | | getBaggage() | Get raw baggage string | | getParsedBaggage() | Get baggage as parsed key-value object |

Development

yarn install       # Install dependencies
yarn build         # Compile TypeScript to dist/
yarn test          # Run tests
yarn lint          # Run ESLint

Known issues

  • When the middleware runs inside an already correlated context (registered twice, wrapped in an outer withId, a request replayed from a job), it passes the request through without setting the response headers — the ID is present in the context and in the logs, but the client does not see x-correlationid on the response.

  • enhanceHttpProxy looks the inbound header up under httpHeaderParamName verbatim, while Node lowercases inbound header names. With a non-lowercase name ('X-Request-Id') the inbound ID is not found outside of a correlation context and an empty header is sent instead. Keep httpHeaderParamName lowercase.

  • Does not work well with bluebird.promisifyAll. Alternative solution is to explicitly promisify using native promise:

const redis = require('redis');
const util = require('util');

const client = redis.createClient();
client.setAsync = util.promisify(client.set).bind(client);
client.getAsync = util.promisify(client.get).bind(client);
  • Does not work well with mongoose callbacks. Alternative solution is to use promisified functions:
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

EntityModel.find({name: 'name'}).then((value) => {
    // do something
});