Test Supabase RLS Policies: The Complete Practical Guide

When you test Supabase RLS policies the right way — pgTAP in the test database, role-switching in the SQL editor, and a CI gate — a broken policy becomes a failing test instead of a leaked dataset.

Last updated: 2026-10-10 Most data-leak stories about Supabase apps share one root cause: RLS policies that were written once, eyeballed once, and never tested. A policy that looks correct in the dashboard can silently allow anonymous reads — and you will never notice, because a denied-by-RLS query returns an empty result, not an error. Your app looks fine while your data walks out the door. The fix is not to "be more careful." The fix is a test suite that asserts what each role can and cannot do, and runs it before every deploy. If you test Supabase RLS policies the way this guide shows — quick role-switching checks in the SQL editor for development, pgTAP tests in the Supabase test database for rigor, and a CI gate so regressions fail the build — a broken policy becomes a failing test instead of a leaked dataset. What you'll learn Why RLS failures are silent and why eyeballing policies in the dashboard proves nothing How to test RLS policies in the SQL editor by switching to the anon and authenticated roles How to write pgTAP tests and run them with supabase test db in the local test database How to build an allow/deny matrix covering anon, owner, and other-user cases for every operation How to test Supabase RLS policies as different users using request.jwt.claims How to wire RLS regression tests into CI so a policy change fails the build before it ships Where pgTAP, SQL-editor checks, and client-side tests each belong (decision table included) The fastest check: test RLS policies in the SQL editor Before writing a test file, check any policy in under a minute from the dashboard. The SQL editor connects as the postgres superuser, which bypasses RLS — so a query that "works" there proves nothing. Drop down to the roles your client actually uses: Wrap everything in…

Explore