hn.today

Row-level security performance in PostgreSQL, measured

now-next.nl4 points0 comments
Screenshot of Row-level security performance in PostgreSQL, measured

Tests on PostgreSQL 17.10 using a 2 million-row, 1,000-tenant invoices table show that row-level security (RLS) itself is effectively free when the policy is a simple equality that matches an index on tenant_id. The experiment used default settings, a warm cache, and recreated policies before runs to force fresh plans. Performance penalties come from three concrete sources: how the policy computes the tenant (inlining and volatility), membership checks written inside the policy, and use of non-leakproof functions that stop the planner using index conditions.

Key findings and fixes: SQL helper functions that can be inlined are fast; PL/pgSQL or VOLATILE helpers that cannot be inlined cause per-row calls and sequential scans (measured slowdowns from ~0.02 s to 1.8-4.6 s), but declaring STABLE (and PARALLEL SAFE when appropriate) or wrapping the call in (select …) restores index use. Membership policies using tenant_id IN (SELECT …) forced per-row checks and added ~80-100 ms to queries; rewriting as = ANY(array(SELECT …)) or, better, resolving membership once and storing the tenant in session eliminates that cost (though the =ANY rewrite can change plans). Non-leakproof functions such as lower() or LIKE cause the planner to apply the function as a Filter rather than an Index Cond, turning millisecond lookups into tens of milliseconds for large tenants; using a stored generated lower-case column or other indexable expressions restores speed. Every measured slowdown correlated with losing an index condition or index ordering; restoring an indexable condition recovered performance.

Read on now-next.nl0 comments on Hacker News

Summary generated by AI from the linked article. hn.today is not affiliated with Hacker News or Y Combinator.

More in Security

The daily digest

Today's best Hacker News stories, summarized and screenshotted, one email a day.