RLS sounds great until it isn't — PlanetScale
PostgreSQL's Row Level Security (RLS) is often seen as an elegant way to enforce access control at the database layer, but it comes with significant pitfalls. Key issues include: policy management complexity that grows with your codebase, incompatibility with connection poolers like PgBouncer (requiring session-local variables per transaction), performance overhead from per-row policy evaluation unless functions are carefully wrapped in subqueries to trigger InitPlan caching, and the fact that table owners and superusers bypass RLS by default. SECURITY DEFINER functions can work around some limitations but push logic back to the application layer anyway. The recommendation is to use application-layer authorization (middleware, ORM scoping, permissions tables) instead, keeping security logic visible, testable, and co-located with application code.