{"id":17603,"library":"exp-correlator","title":"exp-correlator: Async Context and Express Correlation ID","description":"exp-correlator is a Node.js library designed to manage and propagate a correlation ID across asynchronous operations and within Express.js applications. It leverages Node.js's `async_hooks` to automatically track a unique identifier through various async calls, eliminating the need to explicitly pass the ID between functions. The current stable version is 1.0.0, and while a specific release cadence isn't stated, active GitHub workflows suggest ongoing maintenance. Its primary differentiator is the use of `async_hooks` for transparent context propagation, integrating seamlessly as an Express middleware or through a standalone async handler, and providing direct examples for integration with logging libraries like Pino and HTTP clients like exp-fetch.","status":"active","version":"1.0.0","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/BonnierNews/exp-correlator","tags":["javascript","express","middleware","correlation-id","correlation"],"install":[{"cmd":"npm install exp-correlator","lang":"bash","label":"npm"},{"cmd":"yarn add exp-correlator","lang":"bash","label":"yarn"},{"cmd":"pnpm add exp-correlator","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"For `exp-correlator` v1.x, the primary export is CommonJS as shown in the documentation examples. While Node.js `>=14.17` supports ESM, direct `import` might require specific `package.json` configuration or a build step for seamless integration.","wrong":"import { middleware } from 'exp-correlator';","symbol":"middleware","correct":"const { middleware } = require('exp-correlator');"},{"note":"Retrieves the correlation ID from the current async context. Returns `undefined` if no correlation ID context has been established by either the `middleware` or `attachCorrelationIdHandler` in the current async chain.","wrong":"import { getId } from 'exp-correlator';","symbol":"getId","correct":"const { getId } = require('exp-correlator');"},{"note":"Used to manually establish an async context with a correlation ID for a given async function. The correlation ID will be available via `getId()` only within the execution chain of the wrapped function.","wrong":"import { attachCorrelationIdHandler } from 'exp-correlator';","symbol":"attachCorrelationIdHandler","correct":"const { attachCorrelationIdHandler } = require('exp-correlator');"}],"quickstart":{"code":"const express = require('express');\nconst { middleware, getId } = require('exp-correlator');\nconst app = express();\nconst port = 3000;\n\nconst logMessage = async (msg) => {\n  const correlationId = getId(); \n  console.log({ timestamp: new Date().toISOString(), correlationId, msg });\n};\n\n// Simulate an external call that needs the correlation ID\nconst callToExternalSystem = async () => {\n  const correlationId = getId(); \n  console.log({ timestamp: new Date().toISOString(), context: 'external-call', correlationId, message: 'Making external request' });\n  // In a real app, you'd add correlationId to headers, e.g., 'correlation-id'\n  await new Promise(resolve => setTimeout(resolve, 100)); // Simulate network delay\n};\n\napp.use(middleware); // Apply the correlation ID middleware to all incoming requests\n\napp.get('/', async (req, res) => {\n  const initialCorrelationId = getId();\n  await logMessage(\"Request received for /\");\n  await callToExternalSystem();\n  await logMessage(\"After external system call\");\n  res.json({ message: 'Hello World!', correlationId: initialCorrelationId });\n});\n\napp.get('/test', async (req, res) => {\n  const initialCorrelationId = getId();\n  await logMessage(\"Request received for /test\");\n  res.json({ message: 'Test endpoint', correlationId: initialCorrelationId });\n});\n\napp.listen(port, () => {\n  console.log(`Server listening on http://localhost:${port}`);\n  console.log('Try: curl -H \"correlation-id: my-custom-id\" http://localhost:3000');\n  console.log('Or: curl http://localhost:3000/test');\n});","lang":"javascript","description":"Demonstrates how to integrate `exp-correlator` as an Express middleware to automatically track and log correlation IDs across request handlers and nested asynchronous operations without explicitly passing the ID."},"warnings":[{"fix":"Upgrade your Node.js runtime to version `14.17` or newer.","message":"Reliance on `async_hooks` for context propagation means `exp-correlator` requires Node.js `v14.17` or higher. Running on older Node.js versions will result in runtime errors.","severity":"gotcha","affected_versions":"<14.17"},{"fix":"Ensure all code paths intended to access a correlation ID are wrapped by `attachCorrelationIdHandler` or are part of an Express request handled by `middleware`. Debug complex async patterns to confirm context is maintained.","message":"If `getId()` returns `undefined`, it indicates that the code is executing outside an `exp-correlator` context initialized by either the `middleware` or `attachCorrelationIdHandler`. This often happens with event emitters or certain callback patterns that inadvertently break the async flow.","severity":"gotcha","affected_versions":">=1.0"},{"fix":"Profile your application under anticipated load. For extreme performance-critical paths where correlation IDs are not strictly necessary, consider opting out or using alternative, explicit passing mechanisms if `async_hooks` overhead is problematic.","message":"While powerful for transparent context management, `async_hooks` can introduce a slight performance overhead in extremely high-throughput applications or those with deeply nested and frequently invoked async operations. Monitor CPU and memory usage under load.","severity":"gotcha","affected_versions":">=1.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure `const app = express();` is executed before attempting to apply `exp-correlator`'s middleware.","cause":"The Express `app` instance was not properly initialized or is not available when `app.use(middleware)` is called.","error":"TypeError: Cannot read properties of undefined (reading 'use')"},{"fix":"Verify that the `middleware` is correctly applied to your Express app or that `attachCorrelationIdHandler` wraps the entry point of your async operation. Review complex async patterns to ensure context is not inadvertently broken.","cause":"The async context for the correlation ID was not properly established, or it was lost due to an unhandled async boundary (e.g., certain event emitter callbacks, `setImmediate` without proper async context propagation).","error":"correlationId is consistently 'undefined' in logs or when retrieved by getId()"},{"fix":"Upgrade your Node.js runtime to version `14.17` or newer to ensure compatibility and correct functionality.","cause":"The application is running on an unsupported Node.js version, which lacks necessary `async_hooks` features or stability.","error":"Error: `exp-correlator` requires Node.js version `14.17` or higher."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}