Multi-Tenant Architecture Patterns
Multi-tenancy decides how content, config, and API access are partitioned across clients, brands, or business units — and which isolation tier you pick sets your caching, deployment, governance, and fetch complexity. This page compares three tiers, their tradeoffs, and the cross-cutting cache and governance controls. Tenant boundaries shape everything downstream in Headless CMS Architecture & Platform Selection, from schema design to CDN strategy.
1. Shared database, shared schema (tenant-ID filtering)
All tenants share tables or collections. Every record carries a tenant_id or site_id, and the API enforces row-level security by injecting a tenant filter into every query. This is the default for SaaS CMS providers and high-volume agency portfolios.
Implementation Blueprint:
# cms-config.yaml
tenancy:
mode: shared-schema
tenant_header: X-Tenant-ID
fallback_tenant: default
query_injection: strict
audit_trail: enabled
Frontend Fetch Pattern:
async function fetchContent(endpoint, tenantId, query) {
const response = await fetch(endpoint, {
method: "POST",
headers: {
"X-Tenant-ID": tenantId,
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.CMS_TOKEN}`
},
body: JSON.stringify(query)
});
if (!response.ok) throw new Error(`Tenant fetch failed: ${response.status}`);
return response.json();
}
Caching: Cache keys must vary by tenant. Without Vary: X-Tenant-ID or cache-key normalization, you serve Brand A’s content to Brand B. Use tenant-scoped cache tags (purge:tenant:acme) for granular invalidation that doesn’t flush the whole edge.
Tradeoffs:
- ✅ Lowest cost, fastest provisioning, unified caching, simple migrations.
- ❌ Cross-tenant leakage if query injection fails; awkward single-tenant backup/restore; global schema changes hit all tenants at once. See Multi-tenant headless CMS architecture explained for the routing detail.
2. Shared database, isolated schema (per-tenant collections)
Tenants share a database instance but live in separate namespaces, schemas, or collections; the CMS routes to tenant-specific structures at the storage layer. Stronger boundaries, still efficient.
Implementation Blueprint:
{
"tenancy": {
"mode": "isolated-schema",
"routing_strategy": "path-prefix",
"tenant_prefix": "/tenants/{tenantId}/api/v1",
"schema_versioning": "per-tenant"
}
}
Content modeling: Isolated schemas let tenants diverge without breaking each other. Use shared base types (Hero, Footer) with tenant-specific extensions instead of duplicating models — see Content Modeling Best Practices to avoid schema sprawl. This keeps component libraries consistent while allowing editorial flexibility.
Tradeoffs:
- ✅ Stronger isolation, per-tenant schema versioning, simpler compliance auditing, less cache collision.
- ❌ Higher storage overhead, slower onboarding, fragmented caching. Needs careful index management across namespaces as tenant count grows.
3. Fully isolated infrastructure (per-tenant instances)
Each tenant gets a dedicated instance, database, and API endpoint, orchestrated via containers (Kubernetes, Docker) or serverless with independent scaling.
Infrastructure-as-Code Blueprint (Terraform):
resource "cms_instance" "tenant" {
for_each = var.tenants
name = "cms-${each.key}"
region = each.value.region
db_isolation = "dedicated"
api_version = "v2"
tags = {
tenant = each.key
environment = each.value.env
}
}
API strategy: Isolated endpoints mean frontends juggle multiple base URLs, which reshapes the GraphQL vs REST API Tradeoffs — GraphQL’s single endpoint becomes tenant-specific, needing dynamic resolution at build or runtime. Front it with an API gateway or service mesh to route requests, normalize auth, and aggregate telemetry.
Tradeoffs:
- ✅ Maximum isolation, independent scaling, predictable SLAs, granular backup/restore.
- ❌ Highest infrastructure and operational cost, complex CI/CD, fragmented monitoring. The AWS Well-Architected Framework for SaaS covers hardening these pipelines.
Cross-cutting controls
CDN caching
Map tenant boundaries to cache segmentation: Cache-Control: s-maxage=86400, stale-while-revalidate=3600 plus tenant-scoped surrogate keys. See Cloudflare Cache Control Guidelines for edge patterns that prevent cross-tenant poisoning.
DX metrics
Track tenant provisioning time, API latency p95/p99, cache hit ratio, and schema deploy success. Tenant-aware dashboards isolate regressions before they reach a client.
Governance
The tier sets your audit model: shared-schema needs application-level logging, isolated infrastructure enables database-level compliance reporting. Add CI policy checks that validate tenant boundaries before content or schema merges.
Decision matrix
| Requirement | Recommended Tier |
|---|---|
| High tenant volume, uniform content models, cost-sensitive | Shared Schema |
| Moderate tenant count, divergent content models, compliance auditing | Isolated Schema |
| Enterprise SLAs, strict data residency, independent scaling | Fully Isolated |
Pick the tier that matches your operational maturity, governance requirements, and delivery architecture. Multi-tenant design is an evolving contract between infrastructure, content operations, and frontend pipelines, not a one-time config.