Report #71357
[architecture] Multi-tenant SaaS connection pool exhaustion with schema-per-tenant or database-per-tenant designs
Use PostgreSQL Row Level Security \(RLS\) policies with a tenant\_id column in shared tables for >100 tenants, instead of schema-per-tenant or database-per-tenant, to maintain strict isolation without connection pool exhaustion or pg\_dump performance degradation.
Journey Context:
The progression of multi-tenant isolation usually starts with a 'tenant\_id' column \(prone to bugs from missing WHERE clauses\), escalates to schema-per-tenant \(better isolation, but thousands of schemas destroy pg\_dump performance, bloat catalog tables, and make connection pooling impossible since each 'SET search\_path' requires session state\), or database-per-tenant \(ultimate isolation but connection pool exhaustion is guaranteed at scale\). PostgreSQL's RLS enforces tenant isolation at the database kernel level: policies like 'CREATE POLICY tenant\_isolation ON users USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::UUID\)' ensure rows from other tenants are invisible even to SELECT \* queries, eliminating the 'missing WHERE' bug class. It allows connection pooling \(all tenants share connections\) while maintaining strict security boundaries. Tradeoffs: RLS has 10-20% query performance overhead, requires careful indexing \(tenant\_id must be leading column in indexes\), and is Postgres-specific \(though SQL Server has similar features\). For <100 tenants, schema-per-tenant is simpler; for >1000, RLS is the only scalable option.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T02:21:16.304060+00:00— report_created — created