Will enabling RLS break my app? What actually changes
Yes — enabling Row Level Security denies every row to client callers until a policy explicitly grants access, so switching it on without adding policies breaks reads and writes immediately and completely. Add the policies and the flag in the same migration, and the window closes before anyone notices.
This page explains precisely what changes the instant the flag flips, the ordering that avoids an outage, the four ways apps break anyway, and how to recover if you are already broken. It is hand-written guidance: predicting application behaviour is beyond any scanner, and the page says where the automated checks begin and end.
RowShield does not detect this yet. This guide gives you the catalog queries to check it yourself. The nine rules that do ship are listed on the rules index.
What changes the moment the flag flips
RLS is deny-by-default. Once enabled, every query from anon and authenticated roles consults policies, and a table with zero policies grants nothing — lists render empty, forms fail quietly, and the app appears merely haunted rather than broken. Server code connecting with the service_role key notices nothing, because that role carries BYPASSRLS; nor does the table owner without FORCE, which is its own gap worth closing. Storage and Realtime maintain separate policy surfaces, so protecting tables leaves buckets and channels to their own review.
The order that avoids an outage
Inventory the table and decide who legitimately reads and writes it. Generate policies from the real ownership column — user_id, org_id, whichever expresses it — covering SELECT plus INSERT, UPDATE and DELETE with WITH CHECK clauses. Then ship enable, force and policies as one migration so no deploy exists in the deny-all state:
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY; ALTER TABLE public.documents FORCE ROW LEVEL SECURITY; CREATE POLICY "owners_read_own_documents" ON public.documents FOR SELECT TO authenticated USING (user_id = (SELECT auth.uid())); CREATE POLICY "owners_write_own_documents" ON public.documents FOR ALL TO authenticated USING (user_id = (SELECT auth.uid())) WITH CHECK (user_id = (SELECT auth.uid()));
Four ways apps break anyway
First: auth.uid() returns null for anonymous visitors, so a supposedly-public read scoped to it denies guests the moment RLS engages — public surfaces need a policy addressed to anon, deliberately written. Second: mixed signals confuse diagnosis, because the server keeps working on service_role while every browser path dies on anon, sending you debugging the wrong layer. Third: recreated tables shed their policies, so next sprint's drop-and-recreate silently reverts this one. Fourth: policies scoped to service_role only protect nothing, since that role never consulted them.
Recovering if you are already broken
Add the missing policy for the failing call — the error names the table, and the catalog shows what exists. If triage pressure demands it, disabling RLS restores old behaviour instantly and also restores the exposure, so treat it as a timed decision rather than a fix. Prefers adding a permissive-but-scoped interim policy over dropping protection permanently, because interim states have a way of becoming permanent ones.
Verifying, and keeping it verified
Verify as the caller, not the admin: a GET against the table with the anon key alone should return the public subset and nothing more. Automated coverage resumes from there — RLS_NO_POLICIES catches the enabled-but-empty state on every scan before your users do, and scheduled diffs turn the recreated-table failure into an alert naming the table. To mark the boundary honestly, RowShield does not automate predicting what your screens will render; the database side is watched continuously while application behaviour stays a human test. RowShield is an independent product, not affiliated with or endorsed by Supabase. Run a free audit at rowshield.dev/audit — no account needed.
Frequently asked
- Should I enable RLS on every table at once?
- Small projects can migrate in one commit; larger ones fare better grouped by feature area, each group shipping enable-plus-policies atomically so no intermediate deny-all state reaches users.
- Does enabling RLS affect my server code?
- Code connecting with the service_role key bypasses policies entirely and keeps working unchanged. Browsers using the anon key are the affected callers, which is exactly the layer the change is meant to constrain.
- Can I roll back if something fails?
- Disabling RLS restores prior behaviour and the prior exposure simultaneously. Prefer fixing the policy that failed; if you must disable, time-box it and treat the revert as an incident with an owner.
Check your project in about ten seconds
Paste a URL. No signup, no writes, nothing stored.
Run the free audit