technique

Row-level security (RLS)

Row-level security is a Postgres feature where access policies are enforced per-row at the database layer — Supabase's primary auth pattern, foundational for multi-tenant apps that talk to Postgres directly from the client.

Traditional web apps put authorization in the app layer: the API server checks the user, then queries the database. Row-level security flips that: the database itself enforces 'user can see / modify only their own rows' via SQL policies. This unlocks client-direct database access (Supabase's flagship pattern) — the JS client hits Postgres directly, JWT in the request, RLS policies validate each row. By 2026 RLS is the standard for serverless / Jamstack apps using Postgres. Failure modes: missing policies expose data ([[supabase-rls-needs-real-auth]] is a common bug), overly permissive policies grant cross-tenant access, performance issues when policies require subqueries on every row.

When to use row-level security (rls)

Common mistakes

FAQ

What is row-level security (rls)?

Row-level security is a Postgres feature where access policies are enforced per-row at the database layer — Supabase's primary auth pattern, foundational for multi-tenant apps that talk to Postgres directly from the client.

When should I use row-level security (rls)?

Multi-tenant SaaS on Postgres / Supabase. Client-direct database access patterns.

What are the most common mistakes with row-level security (rls)?

Forgetting to ENABLE RLS on a table — all rows exposed by default. Using `auth.uid()` without a real authenticated session — policy denies everything silently.

Last updated: 2026-06-01. Raw markdown: https://promtable.com/glossary/row-level-security.md.