🏗️ Architecture

Multi-Tenant Data Flow

How requests are scoped to tenants throughout the stack.

Request Flow

Diagram; its source is available below
Diagram source
sequenceDiagram
    Client->>API: Request + JWT
    API->>JWT: Decode tenantId
    JWT->>RequestContext: Set tenantId
    RequestContext->>Guard: TenantPermissionGuard
    Guard->>Service: tenantId filter active
    Service->>Repository: WHERE tenantId = :id
    Repository->>Database: Scoped query
    Database-->>Client: Tenant-specific data

Layer-by-Layer

1. JWT Token

Every JWT contains the tenantId:

{
  "id": "user-uuid",
  "tenantId": "tenant-uuid",
  "role": "ADMIN",
  "exp": 1735689600
}

2. RequestContext

RequestContext stores the current tenant in async local storage:

RequestContext.currentTenantId(); // returns tenant UUID

3. Guard Layer

TenantPermissionGuard validates:

  • Token contains valid tenantId
  • Tenant exists and is active

4. Service Layer

All services extend TenantAwareCrudService which auto-filters by tenant:

// Automatically adds WHERE tenantId = :currentTenant
const tasks = await this.taskService.findAll();

5. Repository Layer

Query builders append tenant filter:

SELECT * FROM task
WHERE "tenantId" = 'tenant-uuid'
  AND "organizationId" = 'org-uuid'

Cross-Tenant Access

Only SUPER_ADMIN role can access data across tenants.

Edit this page

Copyright © 2023-Present Ever Co. LTD.Docs by Sourcey