Skip to main content
Use this when Row Level Security predicates protect tenants or other sensitive boundaries. supaschema compares policy definitions structurally. A changed USING expression, WITH CHECK expression, command, role list, or permissive/restrictive mode is treated as a real schema change.

Use this when

  • Policy bodies are part of your access-control model.
  • Reviewers need to see tenant-isolation changes.
  • CI should catch drift between policy files and the database.
  • Deploy should block when configured RLS safety rules fail.
  • Supabase projects use auth.uid() or platform roles in policies.

Do this

Keep policies in the declarative tree near the protected tables:
database/schemas/
  020_invoices.sql
  021_invoices_policies.sql
Generate and check every policy change:
npx supaschema diff
npx supaschema check
Review whether each predicate broadened reads, weakened writes, or changed role coverage. For apply workflows, keep workflow.rls_safety at deploy_blocking so supaschema sync refuses to mutate a target when RLS diagnostics fail.

Verify

Block drift in CI:
npx supaschema diff --fail-on-diff --quiet
Use Supabase stubs when verifying against bare PostgreSQL:
npx supaschema verify --ensure-environment --ensure-roles

Supabase comparison

See why structural policy diffs matter.

CI gate

Gate policy changes before merge.

Check command

Surface policy changes with safety diagnostics.

Sync command

Block unsafe RLS changes before local or remote apply.
Last modified on June 18, 2026