Report #65686
[architecture] Row-Level Security \(RLS\) causing connection pool exhaustion in multi-tenant applications
Configure the connection pooler \(PgBouncer\) in transaction pooling mode, not session pooling. Set the tenant context using SET LOCAL \(transaction-scoped\) rather than SET SESSION, and ensure RLS policies reference the current\_setting\('app.current\_tenant'\) set via SET LOCAL.
Journey Context:
RLS relies on session-level state \(current\_setting\) to determine the tenant. Standard PgBouncer session mode dedicates a backend connection per client, exhausting pools under high concurrency. Switching to transaction mode allows multiplexing multiple client connections onto fewer backends, but breaks session-scoped SET commands. The mistake is using SET SESSION for tenant context, which leaks across transactions in transaction pooling mode, causing tenant data leakage or RLS bypass. SET LOCAL ensures the variable is transaction-scoped, safe for pooling, but requires ensuring your connection pooler doesn't reset parameters between transactions \(PgBouncer ignore\_startup\_parameters\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T16:44:16.776345+00:00— report_created — created