scribase
Free tool

Generate a Row Level Security policy

Pick the shape your table's access control actually needs, fill in your real table and column names, and get the exact SELECT, INSERT, UPDATE, and DELETE policies to paste into a migration — no more copying an example that almost fits.

Each row belongs to one user. Only that user can see or change it.

Ready

Each row in documents is visible and writable only to the user named in its user_id column. The insert policy has only a WITH CHECK: a row does not exist yet while it is being created, so Postgres checks the new row instead, and that check forces user_id to be the inserting user.

documents.sqlsql
alter table public.documents enable row level security;

create policy "documents_select_own"
  on public.documents
  for select
  using (user_id = (select auth.uid()));

create policy "documents_insert_own"
  on public.documents
  for insert
  with check (user_id = (select auth.uid()));

create policy "documents_update_own"
  on public.documents
  for update
  using (user_id = (select auth.uid()))
  with check (user_id = (select auth.uid()));

create policy "documents_delete_own"
  on public.documents
  for delete
  using (user_id = (select auth.uid()));

Check it before you run it

On Scribase, every migration runs through a lock-safety and RLS lint before it applies — a table shipped without Row Level Security is refused, not merely flagged. $25 a month flat, Supabase-compatible.

FAQ

Questions people ask

Is this specific to Supabase?

No — it generates plain Postgres Row Level Security SQL (ENABLE ROW LEVEL SECURITY, CREATE POLICY). auth.uid() is a Supabase/Scribase convention for "the current user's id"; on plain Postgres, swap it for however your app sets the current user (e.g. a session variable read through current_setting()).

Why does the insert policy have no USING clause?

A row does not exist yet while it is being inserted, so there is nothing for USING to check against, and Postgres refuses USING on an INSERT policy. WITH CHECK is what enforces the rule: it runs against the new row and refuses it if the owner column does not match the inserting user.

Does this run against my database?

No. It only produces SQL text for you to review and run yourself. Nothing here connects to a database, and nothing is sent anywhere.

How do I know the generated SQL is safe to run?

Paste it into the migration lock-safety checker below — it runs the same lint a real migration goes through before it applies. To check policies you already have, paste your schema into the RLS checker.