Not everyone sees everything
The reporting tool should only read; the web app shouldn't drop tables; each branch manager should only see their branch's rows. PostgreSQL handles all three with roles, GRANTs and row-level security — enforced in the database, so a bug in one app can't leak everything.
GRANT and policies
CREATE TABLE branch_sales (branch text NOT NULL, amount int NOT NULL);
INSERT INTO branch_sales VALUES ('pokhara', 1200), ('pokhara', 900), ('kathmandu', 2000);
CREATE ROLE reporter;
GRANT SELECT ON branch_sales TO reporter;
CREATE ROLE pokhara;
GRANT SELECT ON branch_sales TO pokhara;
ALTER TABLE branch_sales ENABLE ROW LEVEL SECURITY;
CREATE POLICY own_branch ON branch_sales FOR SELECT USING (branch = current_user);
CREATE POLICY reporter_all ON branch_sales FOR SELECT TO reporter USING (true);
SET ROLE pokhara;
SELECT * FROM branch_sales;
RESET ROLE;
SET ROLE reporter;
SELECT count(*) FROM branch_sales;
RESET ROLE;- Supabase builds its whole security model on RLS policies like these.
- WITH CHECK (…) on INSERT/UPDATE policies controls which rows may be written.
- Apps often pass the user id with SET app.user_id = … and policies read current_setting('app.user_id').