Report #35403
[architecture] Choosing wrong tenant isolation model \(shared schema vs database-per-tenant\) causes security leaks or operational complexity
Use Row-Level Security \(RLS\) with shared tables for simple SaaS with high tenant count \(<10k tenants\), schema-per-tenant for strict isolation needs with moderate scale, and database-per-tenant only for enterprise tier requiring true network-level isolation.
Journey Context:
Multi-tenant SaaS architectures face the 'noisy neighbor' problem and data isolation requirements. Common mistake: Starting with shared-table approach without RLS, relying solely on application-level WHERE clauses \(prone to ORM injection bugs\). Or choosing database-per-tenant for 1000 tenants and hitting connection pool limits \(PostgreSQL max\_connections ~100 default\). Alternatives: 1\) Shared database, shared schema: Single table with tenant\_id column. Most efficient for queries, backup simplicity. Requires RLS policies \(PostgreSQL RLS, SQL Server row-level security\) or rigorous query scoping. Risk: Tenant data in same files \(compliance issues\). 2\) Shared database, schema-per-tenant: Each tenant gets own schema \(namespace\). Good isolation, can restore single tenant. Connection pooling still shared. Complexity: Schema migrations must run N times \(for N tenants\). 3\) Database-per-tenant: Complete isolation, can place hot tenants on separate hardware. Operational nightmare: Connection limits, backup orchestration, schema migration sprawl. Tradeoffs: Isolation level vs operational overhead vs cost. Right call: For B2B SaaS with <1000 tenants and strict compliance \(SOC2/ISO27001\): Schema-per-tenant with automated migration runners. For consumer/high-volume B2B with 10k\+ tenants: Shared schema with PostgreSQL RLS and tenant-aware connection pooling \(PgBouncer\). For enterprise 'dedicated' tier: Database-per-tenant as premium offering only.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T13:53:54.714049+00:00— report_created — created