Supabase Auth plus RLS: keep rows where they belong

Supabase Auth gets you users quickly. Row Level Security (RLS) is what keeps those users from reading each other's rows when you add a second tenant.
This post is the pairing we use on Next.js SaaS apps: model ownership first, then policies that match how you actually query.
Start with the simplest safe data model
Most SaaS apps end up needing an organization/workspace model. A safe baseline looks like:
users(orprofiles) tied toauth.usersorganizationsorganization_members(user ↔ org with role)- Your tables include
organization_id(and sometimescreated_by)
Even if you don’t expose orgs in the UI on day one, modeling ownership early prevents painful migrations later.
RLS: make the database enforce ownership
With RLS enabled, the database will only return rows the current user is allowed to see. That means:
- Even if a buggy API route forgets a filter, your data is still protected.
- You can safely build more features without re-auditing every query.
A practical RLS pattern
For a table like projects:
- Add
organization_idto the row. - Enable RLS.
- Add a policy that checks membership in that organization.
The exact SQL will vary, but the logic is always:
- User can read/write rows where they’re a member of
organization_id.
Don’t trust client input for ownership
Two common mistakes:
- Taking
organization_idfrom the client and writing it directly. - Allowing users to set
created_byarbitrarily.
Prefer server-side derivation:
- Read the active org from session/context
- Enforce it in your server action / route handler
- Let RLS be the final gate
Auth patterns that work well with Next.js
In App Router projects, the best results come from:
- Server-side session checks (Server Components / route handlers)
- A small number of client components for interactive UI
- Minimal “auth logic” duplicated across the app
If you want a deeper breakdown, see /blog/nextjs-app-router-auth-patterns.
Checklist: secure defaults for a template
- RLS enabled on all tenant-owned tables
- A membership table and role columns
- Server-only writes for ownership fields
- API routes validate entitlements server-side
- Clear docs explaining how to extend policies
For a concrete reference, SaaSForge Core ships this pattern at production depth: workspace-scoped RLS, 4-role RBAC, membership tables, and audit logs on mutations. SaaSForge AI adds pgvector for RAG with the same RLS boundaries, and its database docs walk through schema + policies. For the full stack rationale, see our tech stack page.