Report #7656
[architecture] Schema-per-tenant database architecture causing connection pool exhaustion and latency
Avoid schema-per-tenant for high-tenant-count SaaS. Use shared schema with Row-Level Security \(RLS\) for >100 tenants, or database-per-tenant with a connection proxy \(e.g., RDS Proxy, PgBouncer in transaction mode with careful pool sizing\) for strict isolation needs. Never share a connection pool across tenants if you must dynamically SET search\_path per request.
Journey Context:
Architects choose schema-per-tenant believing it offers good isolation without the operational cost of database-per-tenant. They implement it by creating schemas 'tenant\_123' and running 'SET search\_path TO tenant\_123' upon connection checkout. However, connection pools \(HikariCP, PgBouncer\) assume connections are stateless and interchangeable; resetting search\_path on every checkout adds latency, and forgetting to reset causes data leaks. More critically, since each tenant requires a different search\_path, connections cannot be shared between tenants mid-flight. This forces either a dedicated pool per tenant \(exhausting memory/file descriptors with >100 tenants\) or aggressive connection churn \(killing performance\). The hard-won insight is that schema-per-tenant sits in an awkward middle: it lacks the hardware isolation of DB-per-tenant \(shared CPU/memory\) but breaks the pooling assumptions of shared-schema. It is only viable for low-tenant-count \(<50\), low-concurrency scenarios. At scale, shared-schema with RLS \(leveraging PostgreSQL's native security policies\) or database-per-tenant with a robust connection proxy are the only viable paths.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T03:20:56.479307+00:00— report_created — created