Using FaunaDB RBAC to Enforce Trust Boundaries in a Multi‑Tenant App
Learn how to design a minimal, secure RBAC model in FaunaDB for multi‑tenant workloads, with guidance on policy definition, operational checks, and when to revisit the architecture.
07 Jul 2026, 02:50 UTC

Problem Statement
When a SaaS platform serves many tenants, the database must guarantee that each tenant can only see and modify its own data. In FaunaDB, the built‑in Role‑Based Access Control (RBAC) offers a declarative way to enforce these boundaries without custom middleware. The challenge is to design the smallest, most maintainable RBAC schema that satisfies the trust requirements, to monitor its health, and to know when the design no longer fits.
Requirements
- Fine‑grained isolation: No tenant data should be reachable by another tenant’s users.
- Least privilege: Users receive only the permissions they need for their role.
- Dynamic updates: Policies may change as the product evolves without redeploying application code.
- Operational visibility: Security teams should be able to audit policy enforcement and detect misconfigurations.
- Performance: Policy evaluation must not add significant latency to read/write operations.
Minimal Suitable Design
The simplest architecture that satisfies the above uses three layers:
- Tenant‑Specific Collections: Each tenant owns a dedicated collection (e.g.,
Tenant123_Orders). This guarantees physical data separation. - Roles: Two core roles are defined for every tenant:
tenant_admin– full CRUD on all tenant collections.tenant_user– read‑only access to their tenant’s collections.
- Policies: Policies bind the roles to the tenant collections and enforce a
tenantIdclaim in the authentication token.
Example Policy JSON
{
"name": "tenant_admin",
"permissions": [
{"action": "read", "resource": "Tenant123_Orders"},
{"action": "write", "resource": "Tenant123_Orders"}
]
}
Creating Roles and Policies via FQL
Run these commands in the FaunaDB console or through the Node SDK. They require the admin role.
/* Create a role */
CreateRole(
{
name: "tenant_admin",
permissions: [
{ action: "read", resource: "Tenant123_Orders" },
{ action: "write", resource: "Tenant123_Orders" }
]
}
);
/* Assign role to a user */
AddRoleToUser(
{
user: { name: "alice" },
role: { name: "tenant_admin" }
}
);
Replace Tenant123_Orders with the actual collection name for the tenant. For a large tenant base, generate these roles programmatically during tenant onboarding.
Trust/Data Boundaries
FaunaDB’s RBAC enforces boundaries at query time. When a request arrives, the engine checks the caller’s roles against the policy for the target resource. If any policy denies the action, the query is rejected with a 403 Forbidden error and no data is returned. This preserves ACID guarantees because the query never executes on unauthorized data.
Because policies are stored as data, you can version them. Store a policy_version field and validate against the current schema during tenant onboarding. This mitigates accidental privilege escalation during rollouts.
Operational Checks
- Audit Logs: FaunaDB emits
QueryDeniedevents. Configure CloudWatch or a log aggregator to alert on repeated denied requests from the same tenant. - Latency Monitoring: Compare
ReadLatencyandWriteLatencymetrics with and without policies. A sudden spike may indicate overly complex policies. - Policy Validation Tool: Write a simple script that simulates a tenant’s user performing all allowed actions and verifies that denied actions return the expected error code.
- Role Drift Detection: Periodically query
GetRolefor all tenant roles and compare against the expected permission set.
Failure Modes
- Policy Misconfiguration: A typo in a resource name or missing action can silently grant or deny access. Mitigation: automated validation before role creation.
- Privilege Escalation via Role Inheritance: Hierarchical roles can inadvertently accumulate permissions. Mitigation: document the inheritance tree and audit it regularly.
- Performance Degradation: Complex policies with many conditions (e.g., checking dynamic data) increase evaluation time. Mitigation: keep policies simple and cache common checks if possible.
- Cross‑Tenant Leak via Shared Collections: Accidentally assigning a role that references a shared collection exposes data. Mitigation: enforce naming conventions and automated checks.
When to Redesign
- Regulatory Requirement for Network Isolation: If compliance mandates that tenant data must reside in separate physical databases, move from shared collections to per‑tenant databases.
- High Latency Observed: If policy evaluation adds >50 ms average latency under load, consider simplifying policies or moving heavy checks to application logic.
- Tenant Growth Outpaces Role Management: When hundreds of tenants lead to thousands of roles, the role store becomes a bottleneck. Use hierarchical roles or tenant‑level role templates.
- Security Incident Involving Role Escalation: A breach that shows role inheritance was misused warrants a review of the RBAC model and possibly a shift to attribute‑based controls.
Conclusion
FaunaDB’s RBAC is a powerful tool for enforcing trust boundaries in a multi‑tenant environment. By structuring the design around tenant‑specific collections, minimal roles, and simple policies, you achieve strong isolation with low operational overhead. Regular audits, performance monitoring, and clear failure‑mode mitigation plans ensure the architecture remains robust as the tenant base grows.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.