Lesson 8 / 25

Writing Policies With auth.uid()

Using and with check.

USING and WITH CHECK

A policy targets a table, a command (select, insert, update, delete or all) and roles (to authenticated). The USING expression filters which existing rows are visible or affected; WITH CHECK validates new or changed rows on insert and update. Comparing a column with auth.uid() gives owner-only access. Wrapping it as (select auth.uid()) lets Postgres evaluate it once per statement instead of per row, which Supabase recommends for performance.

Owner-only notes

Four policies, one per command.

create policy "read own notes" on public.notes
  for select to authenticated
  using ((select auth.uid()) = user_id);

create policy "insert own notes" on public.notes
  for insert to authenticated
  with check ((select auth.uid()) = user_id);

create policy "update own notes" on public.notes
  for update to authenticated
  using ((select auth.uid()) = user_id)
  with check ((select auth.uid()) = user_id);

create policy "delete own notes" on public.notes
  for delete to authenticated
  using ((select auth.uid()) = user_id);

Index the policy columns

Policies act like extra WHERE clauses; an index on user_id keeps them fast on large tables.

Quick check: Which clause validates the values of a newly inserted row?

  • GRANT
  • USING
  • WITH CHECK
  • RETURNING
Answer

WITH CHECK — USING filters existing rows; WITH CHECK validates new ones.