Report #83229
[architecture] Severe query performance degradation and timeouts when using PostgreSQL Row Level Security \(RLS\) for multi-tenancy with complex policies or subqueries
Implement RLS policies using only simple equality checks on indexed tenant\_id columns: USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::UUID\). Avoid subqueries, function calls, or joins in policies. Set security\_barrier on views used with RLS.
Journey Context:
RLS applies predicates before planning in some paths, but complex policies defeat predicate pushdown and index usage, causing sequential scans. Common anti-pattern: 'tenant\_id IN \(SELECT id FROM accessible\_tenants\)' runs per-row. Alternative schema-per-tenant provides isolation but operational hell \(connection pools, migrations\). Application-level filtering risks authorization bypass bugs. RLS is correct when tenant\_id is indexed and policy is simple equality. Critical: Pass tenant\_id via session-level configuration \(current\_setting\) rather than query parameters to avoid plan cache pollution and SQL injection risks. Always EXPLAIN \(ANALYZE, BUFFERS\) with RLS enabled \(SET row\_security = on\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T22:17:22.669488+00:00— report_created — created