bhylu.com

Advertisements

Node.js AsyncLocalStorage

AsyncLocalStorage can carry context through an asynchronous call chain. It is useful for request identifiers without putting one mutable current-request variable in global scope.

How it works

Each run creates a context for one logical operation. Read the stored value only where the application has established that context, and avoid treating it as authorization evidence supplied by a trusted identity system. This fixture interleaves two asynchronous tasks and proves that each still sees its own identifier. It is not distributed tracing or propagation across a separate worker, child process or remote service.

Run the code

Run this example locally with Node.js. The exact sources are reviewed on Node 22.15.1 and Node 24.22.1 unless a specialised lab states otherwise. Save the complete source as request-context.mjs in a separate empty exercises folder and run node request-context.mjs. There is no Node.js browser runner on Bhylu; the plain JavaScript playground does not provide these filesystem, server or process APIs.

Download the complete source. Ordinary Node scripts need no Apache, PHP or MySQL service. File examples own their temporary folders; network fixtures use loopback and available temporary ports.

Example

request-context.mjs

import { AsyncLocalStorage } from 'node:async_hooks';
const storage = new AsyncLocalStorage();
const task = (id) =>
  storage.run({ id }, async () => {
    await Promise.resolve();
    return storage.getStore().id;
  });
console.log((await Promise.all([task('r-a'), task('r-b')])).join(','));
console.log(storage.getStore() === undefined);

Expected result

r-a,r-b
true

The two task results retain their own context and no request context leaks into the outer scope. A logger can read a deliberately established identifier from this store instead of relying on an order-dependent global variable.

Use the Node.js API reference for the precise version contract.