Backend-only Supabase access: a cleaner pattern for sensitive products
A thoughtful backend-only Supabase security pattern for sensitive tables, combining revoked client grants, server routes, explicit authorization, and RLS defense in depth.
Inside this guide
- Sensitive workflows are easier to secure when the browser cannot query tables directly.
- Server routes centralize auth, authorization, rate limits, logging, and validation.
- RLS remains valuable as defense in depth and migration drift detection.
Direct client access is a tradeoff
Supabase makes direct browser access productive. For low-risk data, that can be a good tradeoff. For billing records, tenant membership, admin workflows, private documents, and security scans, direct access expands the review surface.
A backend-only pattern keeps the browser talking to your app, not directly to sensitive tables. The app server decides what operation is allowed and then calls Supabase with trusted credentials.
Use a clear boundary
The browser sends intent: create project, list scans, download report, rerun audit. The server authenticates the user, checks membership or ownership, validates inputs, rate limits the action, and writes an audit event.
Supabase remains the system of record, but not every table becomes a public API surface.
Keep RLS even when access is server-side
Backend-only does not mean abandoning RLS. RLS catches mistakes in scripts, future client code, and unexpected privileged paths. FORCE RLS on sensitive tables where it fits your operational model.
The strongest pattern is layered: no broad client grants, explicit server authorization, RLS policies for defense in depth, and periodic scans for drift.
Migrate incrementally
Start with the riskiest table. Add the server route first, update the UI to use it, revoke client grants, verify direct browser-role access fails, then move to the next workflow.
Do not do a giant rewrite unless you have to. Security improves fastest when each high-risk path gets a complete boundary and a test.
-- after the server route is live
revoke all on table public.scan_results from anon, authenticated;
alter table public.scan_results enable row level security;
alter table public.scan_results force row level security;FAQ
Does backend-only access make Supabase pointless?
No. You still get Postgres, auth integration, Storage, realtime where appropriate, migrations, and APIs. You choose which surfaces are public.
Should small apps use backend-only for everything?
Not always. Use it first for sensitive workflows where mistakes have meaningful blast radius.