Skip to content
d3 Wiki
08.03

Row Level Security patterns

The database enforces who can see and change what, regardless of how it's accessed.

Updated
Oct 3, 2026
On this page

Purpose

The database enforces who can see and change what, regardless of how it's accessed.

Rules

  • RLS enabled on every table in public. No exceptions; a table without policies is unreadable, which is the safe default.

  • Policies are written per operation (select, insert, update, delete) and named "<who> <verb> <table>".

  • Role checks call public.current_role(); ownership checks compare auth.uid().

  • The anon role gets select only, and only where the tool is public-read.

  • service_role bypasses RLS — hence 07.01.

  • Every policy has a test (04.05): a query that must succeed and one that must fail, as each role.

Patterns

-- public read, editors write
create policy "public read pages" on pages for select to anon, authenticated using (true);
create policy "editors insert pages" on pages for insert to authenticated
  with check (current_role() in ('editor','admin'));
-- owner-only rows
create policy "users read own notes" on notes for select to authenticated using (user_id = auth.uid());
-- admin-only table
create policy "admins all on settings" on settings for all to authenticated
  using (current_role() = 'admin') with check (current_role() = 'admin');

Procedure — new table

Create table → enable row level security → write policies in the same migration → write the policy tests → PR.

Owner: Matt · Last reviewed: 2026-09