Report #11236
[architecture] Multi-tenant SaaS: choosing between shared tables, schema-per-tenant, or DB-per-tenant
For most SaaS applications, use a single shared database with Row Level Security \(RLS\) policies and a tenant\_id column. Create policy: CREATE POLICY tenant\_isolation ON users USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::UUID\); Set tenant context per connection/query. Use composite indexes starting with tenant\_id \(tenant\_id, created\_at\). Only use schema-per-tenant if tenants require heavy customization/isolation; never use DB-per-tenant due to connection pool exhaustion.
Journey Context:
DB-per-tenant provides perfect isolation but destroys connection pools \(thousands of tenants = thousands of connections\) and makes schema migrations a nightmare \(run migration N times\). Schema-per-tenant \(PostgreSQL schemas\) offers better isolation than shared tables and allows per-tenant customizations, but schema migrations must be applied to every schema \(slow, error-prone\), and cross-tenant queries are complex \(must union across schemas\). Shared table with RLS scales best: one schema, one migration, shared connection pool. RLS policies add minimal overhead if indexes are tenant-prefixed. Risk: bugs in RLS policy expose data; must test thoroughly. RLS requires setting tenant context correctly \(e.g., via SET LOCAL app.current\_tenant = 'uuid' in transaction\) to prevent leakage.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T12:49:17.457863+00:00— report_created — created