Implementing Multi-Tenancy Patterns
1. Database per Tenant Pattern
| Aspect | Detail |
|---|---|
| Isolation | Highest — separate DB per tenant |
| Pros | Strong isolation; per-tenant backup/restore; per-tenant compliance |
| Cons | Operational overhead; cost; schema migrations × N |
| Best For | Enterprise / regulated tenants |
2. Schema per Tenant Pattern
| Aspect | Detail |
|---|---|
| Isolation | Medium — separate schema in same DB |
| Pros | Cheaper than DB-per-tenant; reasonable isolation |
| Cons | Connection pool per schema; migration N times |
| Routing | Set search_path / current_schema per request |
3. Shared Database Discriminator Pattern
| Aspect | Detail |
|---|---|
| Isolation | Lowest — tenant_id column on every table |
| Pros | Cheapest; easy migrations; great density |
| Cons | Risk of cross-tenant leak; noisy neighbor |
| Required | RLS (row-level security) or always-applied filter |
Example: Postgres RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.tenant_id')::uuid);
-- App: SET LOCAL app.tenant_id = '...' at request start
4. Tenant Isolation Pattern
| Layer | Mechanism |
|---|---|
| Compute | Per-tenant pod / namespace (silo) vs shared (pool) |
| Network | NetworkPolicy per tenant |
| Data | DB-per / schema-per / RLS |
| Cache | Key prefix; per-tenant TTL/quota |
| Identity | Tenant claim in JWT enforced server-side |
5. Tenant Context Propagation Pattern
| Step | Detail |
|---|---|
| Extract | From subdomain / JWT claim / header at edge |
| Store | ThreadLocal / request scope / OTel baggage |
| Propagate | Forward header to all downstream calls |
| Apply | DB filter, cache key prefix, authz check |
6. Tenant-Based Routing Pattern
| Strategy | Detail |
|---|---|
| Subdomain | {tenant}.app.com |
| Path | /t/{tenant}/... |
| Header | X-Tenant-ID |
| Routing Layer | API gateway routes to tenant-specific cell/shard |
7. Tenant Configuration Pattern
| Aspect | Detail |
|---|---|
| Storage | Tenants table with config JSON; or config service |
| Cache | Per-tenant config cached at request start |
| Examples | Branding, feature flags, plan limits, integrations |
8. Per-Tenant Resource Quota Pattern
| Quota Type | Detail |
|---|---|
| API Rate | Requests per minute by plan |
| Storage | GB per tenant |
| Compute | CPU/mem (K8s LimitRange per namespace) |
| Records | Max users / objects |
| Enforcement | Reject 429 / 402 with clear quota info |
9. Tenant-Based Caching Pattern
| Practice | Detail |
|---|---|
| Key Namespacing | tenant:{id}:user:{uid} |
| Per-Tenant Eviction | SCAN + DELETE on tenant prefix |
| Quota | Cap memory per tenant |
| Risk | Forgetting prefix → cross-tenant leak |
Warning: One missing tenant filter can leak data across tenants. Use RLS, decorators, and integration tests that explicitly assert isolation.
10. Tenant Onboarding Pattern
| Step | Detail |
|---|---|
| Provision | Create tenant record, schema/DB, namespace |
| Seed | Default config, admin user, sample data |
| Verify | Smoke tests for tenant |
| Notify | Welcome flow; activation tracking |
| Tools | Workflow engine (Temporal); Terraform per tenant |