Supabase RLS for a multi-tenant SaaS app needs to answer two questions: which organization owns this record, and what may this particular member do with it? Working login proves neither. Before launch, demonstrate that a legitimate customer can complete the intended workflow and that a different customer cannot reach the same records through another screen, an API request or a background job.
This guide turns that requirement into a review a founder and engineer can perform together. It uses a fictional project portal shared by two agencies. The permission matrix and exercises are original planning examples, not results from a MUBBITS client audit. They apply to teams serving US, UK, Canadian and Australian customers without requiring separate country versions of the application architecture.
Key takeaways
- Model organization membership separately from account identity and the currently selected workspace.
- Check allowed and denied reads, writes and file access using real user permissions.
- Treat privileged server paths as their own authorization boundary.
- Keep access expectations, migrations and test evidence together as the product changes.
Start with a customer story, then draw the data boundary
Imagine a portal where Cedar Studio and Harbor Design each manage projects, documents and client comments. A designer may belong to both organizations. A client may see one project without seeing the agency's other work. The currently selected workspace is a navigation choice; it must not become the sole proof of authorization.
Write down the relationship between people, organizations, projects and invitations before choosing policy expressions. Ask whether a member can leave an organization, whether a client can belong to several projects and who can grant access. Those answers determine the permission model. A simple user_id column may fit private notes, but it cannot represent every collaboration rule.
For this example, a project has one owning organization and client access is explicitly granted at the project level. Membership management is restricted to designated administrators. These are design choices for the fictional portal, not universal Supabase requirements. If you need cross-organization collaboration, specify it deliberately rather than creating an exception whenever a query fails.
Treat grants and row policies as separate checks
Supabase's documentation distinguishes table grants, which permit an operation, from RLS policies, which restrict the rows it may affect. Enabling RLS is therefore one part of the access design. Review exposed tables and the permissions of both signed-out and signed-in callers; do not infer safety from a dashboard toggle alone.
Specify read, create, edit and delete expectations independently. In the portal, an editor may update a project's title but must not move the project into a different organization. A client's permission to read an approved file does not imply permission to upload, replace or delete it. An administrator's membership-management powers should also be explicit.
Ask your engineer to show where these rules are enforced and how a schema change preserves them. Keep the migration and the expected behavior in the same review. If a legitimate operation stops working, inspect the relevant grant, identity and policy rather than broadening every permission until the error disappears.
Use two organizations and a permission matrix
Create synthetic Cedar and Harbor records with clearly different names. Use separate test identities for an administrator, an editor, a project client and an unrelated signed-in person. Testing only with a database owner or a privileged server client can give you the wrong assurance about customer access.
For each exercise, record both the response and the stored result. A denied update must leave the record unchanged. A permitted read must return the intended record, not an empty success response. Repeat consequential checks through the ordinary application and the corresponding customer-facing API path.
The following matrix is an acceptance aid for this particular portal. Replace its decisions with your product's rules. Keep the denied cases alongside the successful journey so future changes cannot silently trade isolation for convenience.
| Caller and action | Expected result | Evidence to retain |
|---|---|---|
| Cedar editor reads a Cedar project | Allowed with only the intended project fields. | Correct record and caller identity. |
| Cedar editor requests a Harbor project ID | No Harbor data returned. | Response and unchanged Harbor record. |
| Cedar editor inserts a project owned by Harbor | Rejected; no cross-organization record created. | Attempted ownership value and resulting database state. |
| Editor changes a project's owning organization | Rejected under this portal's ownership rule. | Before-and-after ownership remains Cedar. |
| Cedar client requests another Cedar client's file | Denied unless an explicit project grant allows it. | File download and storage access checks. |
| Former Cedar member reuses an existing session | Access follows the documented revocation behavior. | Removal time, session state and subsequent request result. |
| Signed-out visitor lists projects | No private project information returned. | Public-client result, including counts and search responses. |
Can each customer reach only the records they should?
Bring your roles, organization relationships and synthetic test records. We can scope the permission model and evidence for allowed and denied operations.
Check the paths that do not look like a project screen
Recent r/Supabase discussion has asked how to harden tenant isolation and test different access paths. That is a useful question to bring into a launch review. A community example is a starting point for investigation, not evidence that your policies work or that a particular architecture is always faster.
Walk through document downloads, exports, search, invitations and scheduled reports. In our example, a nightly report uses a server credential and creates one downloadable file per agency. Its job must resolve the intended organization, select the correct records and deliver the file to the intended recipients. A correct interactive project screen does not establish that this job is correct.
Also inspect indirect disclosures. A search result title, a project count or an error mentioning another client's name may reveal information even when the full record is hidden. Agree which metadata is public and test the actual output against that decision.
Keep privileged keys out of shipped applications
Supabase distinguishes public-client keys from privileged secret keys and legacy service_role keys. Privileged credentials bypass RLS and belong in controlled server components. They must not be included in a browser bundle or distributed mobile app. A public key is not a replacement for your permission rules.
For the portal, use customer-scoped access for customer journeys and a separately reviewed privileged path for administrative work. The server still needs to establish who requested the action and which organization the action concerns. Moving a request behind an API does not make that authorization decision disappear.
If you discover a privileged key in shipped code, switch from prevention to incident containment. Identify the credential and its legitimate callers, remove the exposure path and follow the current vendor rotation procedure. Do not assume that adding an RLS policy revokes the leaked key.
Make the release decision from an evidence record
Close the review with a small record: the tested application revision, the relevant schema changes, the identities used, the expected decisions and links to sanitized results. Mark a case untested when it was not exercised. Do not convert a partial matrix into a security certification.
Give failures an owner and an acceptance condition. For example, 'Cedar editor cannot reassign a project to Harbor, while a permitted title edit still succeeds' is reviewable. 'Improve RLS' is not. Recheck the affected journey after the correction and retain enough context for the next engineer to understand why the rule exists.
MUBBITS can help scope access-control engineering around this kind of concrete workflow. Bring your roles, organization relationships and a test environment with synthetic data; the useful deliverable is a permission model and demonstrated behavior, not a promise that one platform choice eliminates security work.
Frequently asked questions
Is enabling RLS enough to isolate SaaS tenants?
No. Review grants, policy behavior, identity and membership handling, files and privileged paths. Demonstrate legitimate operations and denied cross-organization operations with customer-scoped callers.
Should every customer have a separate database?
That depends on isolation requirements, operations, recovery and commercial constraints. This guide examines a shared-database design; it does not establish that shared or separate databases are universally preferable.
Can a hidden button protect an administrative action?
The button can improve the interface, but the action must still be authorized where the request is processed. Test the request directly with a user who should not have the administrative permission.
Let’s work through your next step.
Tell us what you’re building, what you’ve tried, and where you need a hand. We’ll work with you to define a practical way forward.

