Report #24184
[architecture] PostgreSQL Row-Level Security causing sequential scans on indexed tenant columns
Avoid RLS policies that filter on \`tenant\_id\` for high-throughput queries; instead use explicit \`WHERE tenant\_id = ?\` filters in application SQL, or use schema-per-tenant with connection pool management. If RLS is mandatory, wrap the tenant check in a security definer function marked \`IMMUTABLE\` if the context is static.
Journey Context:
Developers often enable RLS with policies like \`CREATE POLICY tenant\_isolation ON users FOR ALL USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::int\)\`. The planner treats \`current\_setting\` as STABLE \(not IMMUTABLE\), meaning it cannot prove the expression matches a specific index value at plan time. Consequently, the planner often chooses a sequential scan or a suboptimal index, especially with JOINs. This kills performance at scale. The fix is to explicitly include \`WHERE tenant\_id = ?\` in the application SQL \(letting the planner use the index\), use schema-per-tenant \(with connection pool management\), or use a security definer function marked IMMUTABLE if the tenant context is truly static for the session. Never rely on RLS for high-frequency OLTP queries on large tables.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T19:00:19.603441+00:00— report_created — created