Provider Scopes

DEFAULT, REQUEST and TRANSIENT

ScopeInstancesUse for
DEFAULT (singleton)One for the whole appAlmost everything (services, repositories)
REQUESTA new one for every HTTP requestPer-request data: tenant id, request id, current user
TRANSIENTA new one for every class that injects itStateful helpers like a logger with a context name
import { Inject, Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import type { Request } from 'express';

@Injectable({ scope: Scope.REQUEST })
export class TenantContext {
  constructor(@Inject(REQUEST) private readonly request: Request) {}
  get tenantId() {
    return this.request.headers['x-tenant-id'] as string;
  }
}

@Injectable({ scope: Scope.TRANSIENT })
export class ContextLogger {
  private context = 'App';
  setContext(name: string) { this.context = name; }
  log(msg: string) { console.log(`[${this.context}] ${msg}`); }
}

Note: Request scope bubbles up: any provider or controller that injects a request-scoped provider also becomes request-scoped, and is created again for every request. That costs performance, so use it only when needed.

Scopes Simulated

Example

Three "requests" hit the app. Watch how many instances each scope creates:

type Scope = 'DEFAULT' | 'REQUEST' | 'TRANSIENT';
let created = 0;

class Thing {
  readonly id = ++created;
  constructor(readonly scope: Scope) {}
}

const singleton = new Thing('DEFAULT');

function handleRequest(reqNo: number): void {
  const requestThing = new Thing('REQUEST');              // one per request
  const consumers = ['OrdersService', 'PaymentsService'];
  for (const consumer of consumers) {
    const transient = new Thing('TRANSIENT');             // one per consumer
    console.log(
      'req', reqNo, consumer.padEnd(16),
      'DEFAULT#' + singleton.id, 'REQUEST#' + requestThing.id, 'TRANSIENT#' + transient.id,
    );
  }
}

for (let i = 1; i <= 3; i++) handleRequest(i);
console.log('total instances created:', created);

Output

req 1 OrdersService    DEFAULT#1 REQUEST#2 TRANSIENT#3
req 1 PaymentsService  DEFAULT#1 REQUEST#2 TRANSIENT#4
req 2 OrdersService    DEFAULT#1 REQUEST#5 TRANSIENT#6
req 2 PaymentsService  DEFAULT#1 REQUEST#5 TRANSIENT#7
req 3 OrdersService    DEFAULT#1 REQUEST#8 TRANSIENT#9
req 3 PaymentsService  DEFAULT#1 REQUEST#8 TRANSIENT#10
total instances created: 10