What Is Role-Based Access Control (RBAC)?
Role-Based Access Control (RBAC) is an authorization model where permissions are assigned to roles, and users are assigned to roles. A user inherits all permissions from every role they hold. The core relationship is: users → roles → permissions, where a permission is defined as an (action, resource) pair — for example, (read, /api/orders) or (delete, invoice). This indirection through roles makes permission management scalable: changing a role’s permissions immediately affects all users who hold that role, without updating individual user records.
RBAC Levels: Flat, Hierarchical, and Constrained
RBAC is not a single model — NIST defines four levels of increasing sophistication:
- Flat RBAC: Users are assigned to roles; roles have permissions. No hierarchy. The simplest form and sufficient for many applications.
- Hierarchical RBAC: Roles form a hierarchy where senior roles inherit all permissions of junior roles. For example, a
managerrole may inherit all permissions of theemployeerole. This mirrors org charts and reduces role explosion. - Constrained RBAC (Separation of Duties): Adds static or dynamic constraints. Static SoD: a user cannot be assigned both
payment_initiatorandpayment_approverroles simultaneously. Dynamic SoD: a user can hold both roles but cannot activate both in the same session. This prevents fraud and insider abuse. - Symmetric RBAC: Extends constrained RBAC with role constraints on both users and permissions.
ABAC: Attribute-Based Access Control
ABAC evaluates policies against attributes of the subject (user), resource, and environment at request time. Instead of pre-assigning role membership, ABAC evaluates rules like:
allow if user.department == resource.department
AND user.clearance_level >= resource.sensitivity
AND time.hour >= 9 AND time.hour <= 17
ABAC is more expressive than RBAC — you can express context-sensitive policies without creating an explosion of fine-grained roles. The trade-off is complexity: policies are harder to audit and reason about. ABAC is best used where RBAC produces role explosion (thousands of fine-grained roles) or where environmental context (time, location, device trust level) must influence authorization decisions. In practice, many systems combine RBAC and ABAC: coarse-grained access via roles, fine-grained via attribute conditions.
ReBAC: Relationship-Based Access Control (Google Zanzibar)
ReBAC derives permissions from an object relationship graph rather than static role assignments. Google’s Zanzibar system (powering Google Drive, Docs, YouTube) is the canonical example. A permission check resolves a path through the graph:
- User
alicecanviewdocumentdoc:123if she is a direct viewer, OR if she is a member of a group that hasviewerondoc:123, OR ifdoc:123is in a folder where she hasviewer. - Relationships are stored as tuples:
(object, relation, subject)— e.g.,(doc:123, viewer, group:eng)and(group:eng, member, user:alice).
ReBAC is ideal for collaborative products with nested sharing (files in folders, issues in projects, resources in organizations). OpenFGA (by Auth0/Okta) and SpiceDB (by Authzed) are open-source Zanzibar implementations. The cost is higher complexity in relationship modeling and recursive graph traversal at query time.
Policy Decision Point and Policy Enforcement Point
Authorization systems separate two responsibilities:
- Policy Decision Point (PDP): Receives an authorization query (who, action, resource), evaluates the policy against that input, and returns
allowordeny. The PDP is stateless and can be called over gRPC or HTTP. It loads policy rules and data (roles, attributes) to make its decision. - Policy Enforcement Point (PEP): Intercepts the actual request (in middleware, a service mesh sidecar, or an API gateway), constructs the authorization query, calls the PDP, and enforces the result. If PDP returns
deny, the PEP returns 403 before the request reaches the business logic.
This separation allows policy to be updated centrally (at the PDP) without changing application code. It also enables policy testing and simulation against the PDP independently of running services. The PEP can be implemented as an HTTP middleware, a gRPC interceptor, or an Envoy external authorization filter.
Open Policy Agent (OPA)
Open Policy Agent is a general-purpose PDP. Policies are written in Rego, a declarative query language. OPA decouples policy from application code — your service sends a JSON input bundle to OPA and receives a JSON decision back. OPA is used in:
- Kubernetes admission control: OPA (via Gatekeeper) validates or mutates resource manifests before they are persisted. Policies enforce naming conventions, resource limits, required labels.
- API authorization: Services call OPA as a sidecar or external service to authorize HTTP requests based on JWT claims, request path, and loaded permission data.
- Data filtering: OPA can return a partial evaluation — a set of conditions to add to a DB query — so the database itself enforces row-level access without loading all rows into the application.
OPA bundles allow policies and data to be distributed to OPA instances via S3 or OCI registries, with periodic polling. This enables centralized policy management without tight coupling to any service deployment.
Database Schema for RBAC
A minimal RBAC schema uses five tables:
users (id, email, ...)
roles (id, name, description)
permissions (id, resource_type, action) -- e.g. ('order', 'read')
user_roles (user_id, role_id) -- many-to-many
role_permissions (role_id, permission_id) -- many-to-many
To check whether a user can perform an action on a resource type, join through user_roles and role_permissions. For hierarchical RBAC, add a role_hierarchy(parent_role_id, child_role_id) table and use a recursive CTE to expand inherited permissions. Index user_roles(user_id) and role_permissions(role_id) for lookup speed.
Caching Authorization Decisions
Authorization checks are on the hot path of every request. To avoid DB round-trips on each check:
- Cache role→permissions mapping in Redis with a TTL (e.g., 5 minutes). Key:
role:{role_id}:permissions, value: serialized set of (resource_type, action) pairs. Invalidate on permission assignment change. - Cache user→roles in the session or JWT. On login, load all role IDs for the user and store in the session or embed in a JWT. This avoids per-request DB lookups entirely.
- Invalidation: When a role assignment changes, publish an event (via Redis pub/sub or a message queue) so all instances evict the affected cache entry. Without invalidation, users may retain stale permissions until TTL expires.
For high-security environments, accept the latency cost of always checking the database (or a fast PDP like OPA sidecar) rather than serving stale authorization decisions from cache.
JWT Claims-Based Authorization
A common pattern is to embed roles or permissions directly in the JWT payload at token issuance time:
{
"sub": "user:42",
"roles": ["editor", "viewer"],
"permissions": ["article:write", "article:read", "comment:read"]
}
The PEP (middleware) verifies the JWT signature and reads claims directly — no DB or cache lookup required. This is extremely fast. The downside is staleness: if a user’s role is revoked, the old token remains valid until expiry. Mitigations include short token lifetimes (15 minutes) with refresh tokens, or maintaining a token revocation list (adds back the lookup cost). Embedding fine-grained permissions bloats the token; embedding only roles and checking permissions locally keeps token size manageable. For most web applications, JWT claims-based authorization with short-lived tokens is the right default.
Common Interview Questions on RBAC LLD
- Design the data model for a multi-tenant SaaS RBAC system where each tenant can define custom roles.
- How would you implement row-level security so users can only read their own organization’s data?
- How do you handle permission changes for currently logged-in users with active JWTs?
- What is the difference between RBAC, ABAC, and ReBAC, and when would you choose each?
- How would you test that your authorization system correctly enforces separation of duties?
See also: Meta Interview Guide 2026: Facebook, Instagram, WhatsApp Engineering
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering
See also: Atlassian Interview Guide