0PricingLogin
NestJS Enterprise Backend APIs · Lesson

Tenant Resolution via Middleware and AsyncLocalStorage

Extract and propagate the active tenant through requests using AsyncLocalStorage context.

The Multi-Tenancy Problem

In a multi-tenant backend, one running instance serves many customers (tenants). Every request belongs to exactly one tenant, and almost every layer needs to know which one: the database connection, query filters, caches, audit logs, even outbound emails.

  • Passing a tenantId argument down through every service method is noisy and error-prone.
  • Forget it once in a query and you leak tenant A's data to tenant B — a critical security bug.

We need to resolve the tenant once at the edge of the request and propagate it implicitly to everything that runs during that request.

Where Does the Tenant Come From?

Resolution strategy depends on your routing model. Common sources, in order of how early they are available:

  • Subdomain: acme.api.example.com → tenant acme.
  • Header: X-Tenant-Id: acme (common for internal/service-to-service calls).
  • JWT claim: a tid claim inside the access token.
  • Path prefix: /t/acme/orders.

Whatever the source, the goal is to turn raw request data into a validated tenant identifier as early as possible — ideally in middleware, which runs before guards, interceptors, and controllers.

function resolveTenantFromHost(host: string): string | null {
  // acme.api.example.com -> "acme"
  const parts = host.split('.');
  if (parts.length < 3) return null;
  const sub = parts[0];
  return /^[a-z0-9-]+$/.test(sub) ? sub : null;
}

console.log(resolveTenantFromHost('acme.api.example.com')); // acme
console.log(resolveTenantFromHost('localhost'));            // null
console.log(resolveTenantFromHost('BAD!.api.example.com')); // null

All lessons in this course

  1. Tenant Resolution via Middleware and AsyncLocalStorage
  2. Schema-per-Tenant Database Connections
  3. Building Configurable Dynamic Modules
  4. Request-Scoped Providers and Their Trade-offs
← Back to NestJS Enterprise Backend APIs