Report #43171
[architecture] Multi-tenant schema-per-tenant hits connection pool and memory limits
Use PostgreSQL Row-Level Security \(RLS\) with a shared table design: add tenant\_id columns, create policies that compare tenant\_id to current\_setting\('app.current\_tenant'\), and enforce that application connections use a non-superuser role that cannot bypass RLS \(since table owners bypass RLS by default\).
Journey Context:
Schema-per-tenant provides strong isolation but each schema consumes shared\_buffers and requires separate connection pool slots; practical limits are typically thousands of tenants before memory and connection exhaustion. Database-per-tenant is even heavier. RLS allows a single shared table with policies like CREATE POLICY tenant\_isolation ON table USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::int\);. Critical implementation details: \(1\) The application must SET app.current\_tenant = '123' on each connection before querying \(or use SET LOCAL in a transaction\), \(2\) The database role used by the app must not be the table owner \(owners bypass RLS by default\), requiring a separate app-specific role, \(3\) All queries should include tenant\_id to allow the optimizer to use partial indexes on tenant\_id. Tradeoff: RLS adds slight query planning overhead and makes it harder to run cross-tenant analytics without elevated privileges.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T02:56:06.405611+00:00— report_created — created