Report #71617
[architecture] Connection pool exhaustion and migration bottlenecks choosing schema-per-tenant for SaaS with >100 tenants
Use Row-Level Security \(RLS\) policies in PostgreSQL with a tenant\_id column for the pool model \(shared schema\) when tenants have moderate data volumes; reserve database-per-tenant only for strict compliance requirements.
Journey Context:
Schema-per-tenant appears to offer data isolation without the overhead of separate databases, but it shatters connection pools \(each schema requires a separate search\_path or connection setting\) and forces you to run DDL migrations serially across thousands of schemas, often hitting operational timeouts. Database-per-tenant provides true isolation but makes monitoring, backups, and connection limits scale linearly with tenant count. The RLS 'pool' model stores all tenants in one table set, using Postgres RLS policies \(CREATE POLICY tenant\_isolation ON users USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::int\)\) to ensure queries only see permitted rows. This shares connections, allows single-migration DDL, and scales to thousands of tenants. Tradeoffs: One compromised superuser account exposes all data \(vs schema/db separation\), and you must ensure every query sets the tenant context or risk leaking data.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T02:47:24.059474+00:00— report_created — created