Cyborged
  • Home
  • Experience
  • Work
  • Blog
  • Contact
  • Home
  • Experience
  • Work
  • Blog
  • Contact

© 2026 Cyborged. All rights reserved.

Cyber Security Anthusiast & Fullstack Web Developer

Back to blog
SupabasePostgreSQLSecuritySaaS

Row Level Security patterns for multi-tenant apps

A deep-dive into Supabase RLS policies for SaaS products — covering per-org isolation, admin bypass patterns, and testing strategies.

February 5, 2024
12 min read
All posts

Row Level Security patterns for multi-tenant apps

Row Level Security is Supabase's superpower for multi-tenant applications. Done right, it means you literally cannot accidentally serve one tenant's data to another — the database enforces the boundary, not your application code.

The Core Pattern

Every table that contains tenant-scoped data gets an org_id column and a policy:

create policy "Users see only their org data"
  on public.items
  for select
  to authenticated
  using (
    org_id = (auth.jwt() ->> 'org_id')::uuid
  );

The auth.jwt() function returns the current user's JWT payload. You can embed any claim you need — including org_id — using Supabase Auth hooks.

Admin Bypass

For an admin dashboard that needs to see all data, use the service role key server-side (never expose it to the client) and it bypasses RLS entirely:

const supabase = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_SERVICE_KEY // bypasses RLS
);

Testing Policies

Always test policies by impersonating different roles in the SQL editor:

set role anon;
select * from posts; -- should only see published rows
reset role;