Supabase RLS Policy Generator
Pick a real access pattern — owner-only, team-based, admin override, or public read — and get strict, separated SELECT/INSERT/UPDATE/DELETE policies with the (select auth.uid()) performance wrapper, required indexes, security warnings, and a script to verify isolation between two real users.
Why this generator is strict by default
Most RLS snippets you find online use a single permissive policy like using (true) or a catch-all FOR ALL, which silently exposes more than intended and is harder to reason about per operation. This tool instead generates one policy per operation, always scopes them with TO authenticated (or an explicit anon grant when you actually want public reads), and wraps Supabase Auth helper functions in select so Postgres can cache them per statement instead of re-evaluating per row.
For team and admin patterns, it also generates a SECURITY DEFINER helper function rather than inlining a join inside the policy — this avoids the classic recursive-RLS trap where a policy on table A queries table B, which has its own RLS that queries table A again.
Frequently Asked Questions
Why not just use "using (true)" for everything?
Because it silently exposes every row to every request that passes your anon key, which is the exact misconfiguration behind large-scale Supabase data leaks. This generator only uses an open read policy for the Public Read pattern, and warns you explicitly when it does.
Why does the SQL wrap auth.uid() in a select statement?
Wrapping helper functions like auth.uid() and auth.jwt() in a select causes Postgres to run an initPlan and cache the result once per statement instead of re-evaluating it for every row. Supabase's own performance testing shows this can be a 100x improvement on large tables.
Why are there 4 separate policies instead of one FOR ALL policy?
PostgreSQL policies don't support multiple operations in a single FOR clause, and separating SELECT, INSERT, UPDATE, and DELETE makes it obvious exactly what each operation allows. It also lets you apply WITH CHECK only where it's actually needed, for writes.
Do I still need to test this manually?
Yes. The Supabase SQL editor runs as the postgres role and bypasses RLS entirely, so a policy that looks correct there can still be broken for real users. Use the generated verification script with two real test accounts before shipping.
Does this tool send my schema anywhere?
No. Everything runs in your browser — table and column names you type are only used to generate the SQL shown on this page, nothing is sent to a server.