Przejdź do głównej zawartości

Multi-Schema Tenancy

Database-level tenant isolation strategies.

Tenant Isolation Models

ModelDescriptionIsolationComplexity
Shared SchemaAll tenants in one DBLowLow
Schema per TenantSeparate schema per tenantMediumMedium
DB per TenantSeparate databaseHighHigh

Gauzy's Approach: Shared Schema with Row-Level Security

Gauzy uses a shared schema model with tenantId on every entity:

export abstract class TenantBaseEntity extends BaseEntity {
@MultiORMColumn()
tenantId: string;

@MultiORMManyToOne(() => Tenant)
tenant: Tenant;
}

Automatic Tenant Filtering

Every query is automatically scoped to the current tenant via:

  1. TenantPermissionGuard — extracts tenantId from JWT
  2. RequestContext — stores tenant info for the request lifecycle
  3. Service base class — applies tenant filter to all queries
// In TenantAwareCrudService
async findAll(filter: any): Promise<IPagination<T>> {
const tenantId = RequestContext.currentTenantId();
return super.findAll({
...filter,
where: { ...filter.where, tenantId },
});
}

PostgreSQL Row-Level Security (Advanced)

For additional database-level enforcement:

ALTER TABLE employee ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON employee
USING (tenant_id = current_setting('app.tenant_id')::uuid);

Cross-Tenant Queries (Admin)

Super admin can query across tenants:

if (RequestContext.hasRole(RolesEnum.SUPER_ADMIN)) {
// Skip tenant filter
return super.findAll(filter);
}