Skip to main content

Supabase Auth plus RLS: keep rows where they belong

CategorySupabase
PublishedFeb 16, 2026
Reading time11 min read
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 (or profiles) tied to auth.users
  • organizations
  • organization_members (user ↔ org with role)
  • Your tables include organization_id (and sometimes created_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:

  1. Add organization_id to the row.
  2. Enable RLS.
  3. 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_id from the client and writing it directly.
  • Allowing users to set created_by arbitrarily.

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.

B

Boilerlykit Team

Security