Relationship-Based Access Control
also called ReBAC, Graph Authorization
Expressing permissions as relationships between subjects and objects, with inheritance and group expansion as rules over the graph, rather than as attributes on rows.
Role-based access control answers "what role does this user have". Attribute-based control answers "what do this user's attributes permit". Neither expresses the question a collaborative product actually asks: does this user have a path to this object through some chain of sharing, group membership and inheritance?
Relationship-based access control stores facts — page:X parent page:Y, user:A editor page:Y,
group:G member user:A — and evaluates authorization as a reachability question over that graph, with
inheritance and group expansion expressed as rules.
Why it exists
Because ad-hoc permission columns cannot express inheritance with overrides at arbitrary depth. A workspace product with pages nested indefinitely, permissions inheritable and overridable at any level, and sharing with individuals, groups and guests, has an effective-permission calculation that depends on an arbitrarily long ancestor chain and on group memberships that are themselves nested.
Encoding that in columns produces a system where nobody can answer "why does this user have access", which is the question that matters during an incident.
Implementation patterns
- Materialise effective permissions, so a check is a lookup rather than a traversal on the hottest path in the product. The trade is that a change high in the tree becomes a fan-out write.
- Bound the propagation — materialise lazily for cold subtrees, eagerly for hot ones, or to a fixed depth with traversal beyond. A permission change at the root of a large workspace must not be synchronous.
- Version tokens per subtree, so a change invalidates cached decisions without enumerating them.
- Check at the data boundary, not only at the API boundary. Search, export, notifications, previews and link unfurling must apply the same check — they are the classic leak paths, because they are built by different teams from different indexes.
- Deny wins, and the model is closed by default.
Industry example
Collaborative document and workspace products are the canonical application, and the design pressure is identical wherever content is deeply nested and widely shared: an issue tracker with project and board hierarchies, a code host with organisation, team and repository nesting, a file store with folder trees.
The property these all share is that permission changes are frequent, the object graph is deep, and a permission check sits on every read. That combination is what forces the relationship model and the materialisation, and it is why large-scale internal authorization services were built as general-purpose graph systems rather than as per-product permission tables.
The failure modes are also consistent across them: search leaking content because the index was built before a permission change and filtering happens against the index rather than current truth; public link sharing becoming an unauthenticated path into the model; a page move silently changing effective permissions for everything beneath it; and group membership changes not propagating, so a departed employee retains access.
Failure scenarios
- Authorization that fails open under load or dependency failure. It must fail closed, which means its availability requirement equals the whole product's.
- Grants and revocations treated symmetrically in caching. Grants may be eventually consistent; revocations may not.
- Unbounded traversal on the hot path, producing variable latency on every read.
- A separate permission implementation per surface, guaranteeing that one of them is wrong.
- No way to explain a decision, so incidents cannot be investigated.
Trade-offs
A dedicated authorization service is a hard dependency on every read, with its own availability, latency and operational burden — and it centralises a concern that was previously distributed and cheap. For a product with a flat permission model and few sharing rules, it is substantial over-engineering.
It earns its cost when permissions are nested, shared across principals of different kinds, and changed often enough that materialisation and invalidation are genuine problems.
Interview question
"Design permissions for a document tool where pages nest arbitrarily, permissions inherit but can be overridden, and pages are shared with people, groups and external guests. Tell me what happens when someone moves a page, and when someone is removed from a group."