Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does AsyncLocalStorage avoid the latency cost of request-scoped providers in NestJS? It can avoid constructing request-lifetime providers when all you need is to carry values such as a request ID, user, tenant, or locale through asynchronous work. That is a design distinction, not proof of a universal speedup: NestJS gives an approximate latency expectation for request scope, but the sources do not establish a general head-to-head performance ratio.

What is the difference?

Request scope controls provider lifetime: NestJS creates provider instances for each incoming request. AsyncLocalStorage controls context propagation: it associates a store with an asynchronous execution so downstream callbacks and promise chains can access the same values while providers remain singleton-scoped.

Decision point Request-scoped providers AsyncLocalStorage context
What varies? Provider instances are created per request. A request-scoped dependency can make its consumers request-scoped too. NestJS injection scopes Context data varies with the asynchronous execution; providers can remain singleton-scoped. Node.js asynchronous context tracking
How is data accessed? Inject the request or transport context, such as NestJS’s REQUEST token or GraphQL CONTEXT. NestJS injection scopes Establish a store at an appropriate request, message, or job boundary, then read it from downstream asynchronous code. NestJS injection scopes
Best fit A service genuinely needs request-lifetime construction or direct access to the request object. Cross-cutting values need to follow asynchronous work, but service construction itself does not need to vary.
Performance evidence NestJS warns that per-request instantiation can affect performance and says a properly designed application using request scope should not see latency increase by more than approximately 5%. This is framework guidance, not a guarantee or comparison with AsyncLocalStorage. NestJS injection scopes It avoids request-scoped provider lifetimes for context-only use, but still has runtime costs. No universal measured speedup over request scope is established by the cited sources.

Why request scope can affect more than one provider

NestJS has three provider scopes. DEFAULT is the default singleton lifetime: one instance is shared across the application. REQUEST creates an instance for each incoming request. TRANSIENT creates an instance for each consumer that injects the provider. NestJS injection scopes

The important DI trap is scope bubbling. If a controller depends on a request-scoped service, the controller also becomes request-scoped. A request-scoped leaf can therefore change the lifetime of providers higher in the dependency chain, increasing per-request construction beyond the class that first needed context. Trace the dependency graph before changing a provider’s scope.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When AsyncLocalStorage is the better fit

Choose AsyncLocalStorage when downstream code needs values such as a request ID, authenticated user, tenant, or locale, but the services consuming those values do not need new instances for each request. NestJS identifies a per-request AsyncLocalStorage store as an alternative to request-scoped providers and documents its use across HTTP handlers, microservice message handlers, and queue jobs. NestJS injection scopes

Node.js describes AsyncLocalStorage as the API for associating state and propagating it through callbacks and promise chains. Its API is stable; it became stable in Node.js v16.4.0. The consulted API documentation is for Node.js v26.10.0. Node.js asynchronous context tracking

Think of the store as execution context, not as a replacement for dependency injection. Use DI to construct and connect services; use the context store to make per-execution metadata available without turning otherwise shared providers into per-request instances.

When request scope is still appropriate

  • A provider’s construction or state genuinely belongs to one request, rather than merely needing access to request metadata.
  • The provider needs direct access to a framework request object or transport context, such as REQUEST or GraphQL CONTEXT. NestJS treats REQUEST as inherently request-scoped. NestJS injection scopes
  • You have checked scope bubbling and accept the instance lifecycle across the affected dependency chain.

Keep request scope away from components NestJS says must remain singleton-scoped. Its documentation warns against using it with WebSocket gateways and names Passport strategies and Cron controllers as examples that should remain singletons. NestJS injection scopes

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Multi-tenant applications: a separate lifetime option

NestJS also documents durable providers and grouped DI subtrees for cases where a stable tenant attribute can be used to reuse a subtree. This is distinct from propagating request context with AsyncLocalStorage: it changes how dependency-injection subtrees are reused. NestJS cautions that this strategy is not ideal for applications with a large number of tenants. NestJS injection scopes

How to decide and validate latency

  1. Identify the actual need. If code only needs to read context values downstream, favor context propagation; if an instance must be constructed per request, consider request scope.
  2. Inspect the dependency graph. Find request-scoped dependencies and determine which controllers and services inherit request scope through bubbling.
  3. Check framework constraints. Keep components that must be singleton, including WebSocket gateways, Passport strategies, and Cron controllers, out of request scope.
  4. Benchmark your application. Compare the alternatives using the same Node.js and NestJS versions, hardware, request complexity, DI graph depth, concurrency, warmup, and measured metrics. Report the conditions alongside any result; do not generalize from a different workload.

NestJS’s approximate 5% figure is guidance for a properly designed application using request-scoped providers, not a promised ceiling for every workload and not an AsyncLocalStorage-versus-DI measurement. A project-maintained benchmark reports measurements for Node.js v24.6.0 on a named local CPU and workload, measured February 14, 2026, and cautions that results vary with Node.js version, hardware, request complexity, and DI graph depth. Treat those results as workload-specific rather than independently validated evidence of a general ratio. pas7-studio benchmark repository

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Practical rule

Choose provider scope for the lifetime a service needs. Choose AsyncLocalStorage when the problem is carrying per-request or per-job context through asynchronous execution. If you are considering either option because of latency, benchmark the actual application rather than assuming that one mechanism is always faster.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.