Report #35834
[architecture] Application connection pool exhaustion when using schema-per-tenant or database-per-tenant architectures
Adopt row-level security \(RLS\) with a shared schema instead of schema-per-tenant; if strict isolation is required, use Citus-style shard keys \(tenant\_id\) rather than separate schemas. Ensure SET search\_path is never used per-request, or use dedicated connection pools per tenant only if tenant count < 100.
Journey Context:
Schema-per-tenant seems architecturally clean for isolation but creates an N:M problem: N tenants \* M application instances = potential database connections. PostgreSQL backends are heavy processes \(MBs of RAM each\), and connection pools \(PgBouncer/HikariCP\) become ineffective when each tenant needs a distinct search\_path or schema context, often requiring connections to be pinned per request. Row-Level Security \(PG9.5\+\) allows true data isolation with a single shared table, enabling connection pooling efficiency and eliminating the SET search\_path overhead. The tradeoff is weaker logical isolation \(tenant data in same physical files\) and the need to correctly set tenant context \(SET app.current\_tenant = 'X'\) on every connection acquire. For SaaS with >1000 tenants, RLS is the only viable path; schema-per-tenant is suitable only for 'enterprise' tiers with <50 tenants where dedicated resources are expected.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T14:37:12.950210+00:00— report_created — created