Every B2B product that scales eventually faces the same question from a customer or auditor: "Walk me through how customer A's data is isolated from customer B." The wrong answer is "application code filters it, and we have tests." Every auditor knows application code has bugs. Every customer who's been burned does too.
The right answer puts the enforcement in the database itself. Postgres row-level security is the only mechanism that holds across migrations, background jobs, webhook handlers, and admin tools — every code path that touches the data, with one rule.
What multi-tenant RLS gives you
- →Customer trust. "It's enforced at the database level" is the answer that ends the security review.
- →Audit posture. SOC 2, HIPAA, GDPR — every framework asks how data isolation works. RLS is the answer that fits on a single page.
- →Defense in depth. Application code can have bugs. Service-role workers can be misconfigured. RLS still holds because the enforcement point is the database itself.
- →Future feature speed. New surfaces — admin dashboards, batch jobs, integrations — can hit the database confidently because tenancy is enforced one place, not everywhere.
The six places RLS gets bypassed
RLS is the right mechanism. It's also where most teams quietly ship their first cross-tenant data leak — not because RLS is hard, but because there are six paths around it that have to be closed before launch.
1. New tables ship with RLS disabled
Postgres creates tables with RLS off by default. You have to explicitly enable it — and force it, so the table owner doesn't bypass it. The fix is a migration template that's followed in every CREATE TABLE.
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
ALTER TABLE projects FORCE ROW LEVEL SECURITY;2. Service-role bypass paths
Background jobs, webhook handlers, and admin tools often run as a privileged role that bypasses RLS entirely. This is the single most common path for accidental cross-tenant access. Audit every code path that uses a service-role connection. Reduce it to two named system tasks; everything else uses an authenticated, RLS-scoped connection.
3. USING vs WITH CHECK
RLS policies have two clauses. USING controls which rows are visible. WITH CHECK controls what they're allowed to become. Without WITH CHECK, a tenant can update a row to belong to another tenant. Both clauses get specified, on every policy, every time.
4. Policies written against users instead of organizations
Policies that say "this user owns this row" work for personal projects and fail for B2B SaaS where users belong to organizations and rows belong to organizations. Write policies against memberships, not user IDs.
5. SECURITY DEFINER views and functions
Functions and views marked SECURITY DEFINER run with the privileges of the definer rather than the caller, bypassing RLS. There are legitimate uses; there are also accidental ones. Audit every SECURITY DEFINER object before launch.
6. Tests that pass without policies
If your test suite runs against a connection that bypasses RLS — the default for most test setups — you can have RLS policies that don't actually work and your tests will pass. Write tests that establish a tenant context, run queries, and assert that other tenants' rows aren't visible. Make the tests fail by removing a policy.
What this looks like at audit time
When the auditor asks how data isolation works, the answer is short: Postgres enforces it at the row level. Here's the policy. Here's the test that proves the policy holds. Here's the query path audit that confirms no privileged code path exists outside two named system tasks.
That answer ends the conversation. The alternative — "application code filters it" — opens a multi-day deep-dive into every endpoint, every job, every integration. Choose the architecture that ends the conversation.
What it costs to do this right
Two extra days of work in week one. A pre-launch audit that walks every query path and asks four questions about each. The cost is small. The benefit is a security posture that survives the worst kind of customer conversation — the one where they want to know, in writing, why they can trust you.
RLS is unsexy work. The audit is unsexy work. Both prevent the worst kind of bug — the kind that takes years to manifest, lands on the wrong day, and ends customer relationships.