Report #8910
[architecture] Row-Level Security \(RLS\) causes full table scans in multi-tenant PostgreSQL
Place tenant\_id as the leading column in composite indexes and write RLS USING clauses with equality operators against session variables
Journey Context:
RLS appears ideal for multi-tenant isolation, but naively implementing \`CREATE POLICY tenant\_isolation ON users USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::int\)\` often forces sequential scans because the planner cannot push RLS predicates into index scans if the predicate is complex \(using functions or non-equality operators\). Common mistake is assuming RLS is transparent performance-wise. The fix is ensuring tenant\_id is the leftmost column in indexes \(tenant\_id, user\_id\) not \(user\_id, tenant\_id\), and writing RLS policies like \`USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::int\)\` with explicit equality. This allows index usage. Also mention that RLS can disable parallel query plans in older PostgreSQL versions.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T06:46:15.451768+00:00— report_created — created