Report #14130
[architecture] Cross-tenant data leakage or complex query filtering in multi-tenant SaaS applications
Use PostgreSQL Row-Level Security \(RLS\) policies to enforce tenant isolation at the database layer: CREATE POLICY tenant\_isolation ON table USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::UUID\). Set the tenant context per transaction using SET LOCAL app.current\_tenant = 'tenant-uuid'.
Journey Context:
The naive approach—adding WHERE tenant\_id = ? to every query—is error-prone; one missed clause leaks data, and ORMs make it easy to forget. Schema-per-tenant provides isolation but explodes operational overhead \(migrations across thousands of schemas\) and breaks connection pooling \(search\_path changes\). DB-per-tenant is operationally expensive and hits connection limits. RLS provides defense-in-depth: even if the application layer has a SQL injection bug, the database enforces the policy. Pitfalls: RLS can disable index usage if policies use non-immutable functions, adds ~5-10% query overhead, and requires careful handling with connection poolers like PgBouncer in transaction mode \(session variables must be set per transaction, not connection\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T20:45:11.974047+00:00— report_created — created