Multi-Tenancy Architecture: Shared vs Isolated Patterns for SaaS
Multi-Tenancy Architecture for SaaS#
Every SaaS app serves multiple customers (tenants) from the same infrastructure. The architecture decision — how much isolation between tenants — affects security, cost, performance, and complexity.
The Three Models#
1. Shared Database (Row-Level Isolation)#
All tenants in the same database, same tables. tenant_id column on every row.
SELECT * FROM orders WHERE tenant_id = 'acme' AND status = 'active';
Pros: Cheapest, simplest, easy to manage Cons: Noisy neighbor risk, one bad query affects all, data leak if you forget WHERE clause Best for: Early-stage SaaS, < 1000 tenants, non-sensitive data
2. Schema-Per-Tenant#
Same database server, separate schema (namespace) per tenant.
-- Tenant A
SELECT * FROM tenant_acme.orders WHERE status = 'active';
-- Tenant B
SELECT * FROM tenant_corp.orders WHERE status = 'active';
Pros: Better isolation, easier backup/restore per tenant, no tenant_id risk Cons: Schema migration across N schemas is complex, connection pooling harder Best for: Mid-stage SaaS, 100-10K tenants, moderate isolation needs
3. Database-Per-Tenant#
Each tenant gets their own database instance.
Tenant A → postgres-acme.rds.amazonaws.com
Tenant B → postgres-corp.rds.amazonaws.com
Pros: Maximum isolation, per-tenant scaling, easy compliance (data residency) Cons: Expensive (N databases), complex provisioning, cross-tenant queries impossible Best for: Enterprise SaaS, regulated industries (HIPAA, finance), large tenants
Comparison#
| Factor | Shared DB | Schema-Per-Tenant | DB-Per-Tenant |
|---|---|---|---|
| Cost | Lowest | Medium | Highest |
| Isolation | Low (row-level) | Medium | Maximum |
| Noisy neighbor | High risk | Medium risk | No risk |
| Migration complexity | Simple | Medium (N schemas) | Complex (N databases) |
| Per-tenant backup | Hard | Easy | Easy |
| Data residency | Hard | Hard | Easy (per-region DB) |
| Cross-tenant queries | Easy (same table) | Possible (same server) | Impossible |
| Scaling | Vertical only | Vertical | Per-tenant |
| Provisioning | Instant (new row) | Fast (new schema) | Slow (new database) |
| Best for | Startups | Growth stage | Enterprise |
Modern Approach: Database Branching#
Tools like Neon and Turso make database-per-tenant affordable:
Neon (Serverless Postgres)#
- Branch creation: < 1 second (copy-on-write)
- Scale to zero when tenant is idle (no cost)
- Thousands of databases per project
Turso (Edge SQLite)#
- Per-tenant embedded replicas (in-app, zero latency reads)
- 10K+ databases per account on free tier
- Global replication per tenant
// Turso: create database per tenant
const db = createClient({
url: `libsql://${tenantId}-myapp.turso.io`,
authToken: process.env.TURSO_TOKEN,
});
Row-Level Security (RLS)#
PostgreSQL's built-in tenant isolation:
-- Enable RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- Policy: users can only see their tenant's data
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.tenant_id'));
-- Set tenant context per request
SET app.tenant_id = 'acme';
SELECT * FROM orders; -- Only returns acme's orders
Supabase uses RLS as its primary security model. Every query is automatically filtered.
Application-Level Patterns#
Tenant Resolution#
How to identify the tenant for each request:
1. Subdomain: acme.myapp.com → tenant = "acme"
2. Path: myapp.com/acme/dashboard → tenant = "acme"
3. Header: X-Tenant-ID: acme
4. JWT claim: { "tenant_id": "acme", ... }
5. API key: sk_acme_... → lookup tenant from key
Subdomain is most common for customer-facing SaaS. JWT claims for APIs.
Tenant Context Middleware#
// Express middleware
app.use((req, res, next) => {
const tenant = req.hostname.split(".")[0]; // acme.myapp.com → acme
req.tenantId = tenant;
// Set database context
db.raw(`SET app.tenant_id = '${tenant}'`);
next();
});
Tenant-Aware Caching#
Cache key: tenant:{tenantId}:resource:{resourceId}
Example: tenant:acme:user:123
Never share cache between tenants. Always include tenant_id in cache keys.
Handling the Noisy Neighbor#
One tenant's heavy query shouldn't slow down everyone:
- Rate limiting per tenant — 100 req/min per tenant, not global
- Query timeout — kill queries running > 5 seconds
- Connection pooling — limit connections per tenant
- Resource quotas — CPU/memory limits per tenant (K8s)
- Queue isolation — separate queues for heavy tenants
Architecture Examples#
Startup SaaS (Shared DB)#
Client → API → PostgreSQL (shared, RLS)
→ tenant_id on every table
→ Redis (tenant-prefixed keys)
→ S3 (tenant-prefixed paths)
Growth SaaS (Hybrid)#
Client → API Gateway (tenant from subdomain)
→ Shared services (auth, billing)
→ Tenant router
→ Small tenants → Shared PostgreSQL (RLS)
→ Large tenants → Dedicated PostgreSQL
→ Redis Cluster (tenant-namespaced)
Enterprise SaaS (Full Isolation)#
Client → API Gateway
→ Tenant A → Dedicated K8s namespace
→ Own PostgreSQL, Redis, workers
→ Tenant B → Dedicated K8s namespace
→ Own PostgreSQL, Redis, workers
→ Shared: Auth, billing, monitoring
Migration Path#
Stage 1 (0-100 tenants): Shared DB + RLS
Stage 2 (100-1K tenants): Schema-per-tenant for large customers
Stage 3 (1K+ tenants): Database-per-tenant for enterprise
Don't over-engineer from day one. Start shared, isolate when you need to.
Summary#
- Start shared — row-level isolation with RLS is simple and cheap
- RLS is your friend — PostgreSQL enforces isolation at the database level
- Subdomain routing for tenant resolution
- Always prefix cache/storage keys with tenant_id
- Rate limit per tenant — prevent noisy neighbors
- Modern tools (Neon, Turso) make DB-per-tenant affordable
- Migrate gradually — shared → schema → dedicated as tenants grow
Design multi-tenant architectures at codelit.io — 112 articles, 100 product specs, 90+ templates.
Try it on Codelit
Chaos Mode
Simulate node failures and watch cascading impact across your architecture
AI Architecture Review
Get an AI audit covering security gaps, bottlenecks, and scaling risks
Related articles
AI Agent Tool Use Architecture: Function Calling, ReAct Loops & Structured Outputs
6 min read
AI searchAI-Powered Search Architecture: Semantic Search, Hybrid Search, and RAG
8 min read
AI safetyAI Safety Guardrails Architecture: Input Validation, Output Filtering, and Human-in-the-Loop
8 min read
Try these templates
Scalable SaaS Application
Modern SaaS with microservices, event-driven processing, and multi-tenant architecture.
10 componentsNetflix Video Streaming Architecture
Global video streaming platform with adaptive bitrate, CDN distribution, and recommendation engine.
10 componentsSearch Engine Architecture
Web-scale search with crawling, indexing, ranking, and sub-second query serving.
8 components
Comments