Authorization models
How do RBAC, ABAC and ReBAC each compress the permission matrix, and what does each lose?
The decision is a yes/no predicate over subject × object × action. Written as a table (a "matrix"), it has |S| · |O| · |A| cells. For a real data platform with 3,000 people, 50,000 tables and 5 actions, that is 3,000 × 50,000 × 5 = 750,000,000 cells. Nobody stores that. So:
RBAC — roles: assume low rank
Role-based access control. It assumes people cluster into a small number of groups who need identical access. Instead of storing subject → permission, you store subject → role and role → permission. Storage drops from a product to a sum. (In matrix language, you assume the matrix has "low rank".)
It works exactly when the assumption holds. It fails by role explosion. If access truly depends on d independent dimensions (region, department, clearance level, purpose), you need roughly 2^d roles to say it. With only 4 independent yes/no dimensions that is 2⁴ = 16 roles; with 11 dimensions it is 2,048, close to Hollis's 2,400. Organizations reach that point quickly. Role explosion is not bad housekeeping. It is a compression scheme being applied to a matrix that does not compress that way.
ABAC — attributes: compress by rule
Attribute-based access control stops listing and evaluates a rule at request time over attributes of the subject, object, action and environment. Example rule: "a clinician may read a lab result if the clinician's hospital equals the patient's hospital and the result is not flagged 'restricted'". A d-dimensional policy becomes one rule instead of 2^d roles.
The cost is rarely stated honestly: you lose auditability by enumeration. "Who can read this table?" used to be a lookup. Now it is a satisfiability question over the policy plus the current value of every attribute from every source. You have bought expressiveness by giving up the ability to answer the inverse question.
ReBAC — relationships: assume transitivity
Relationship-based access control assumes the policy is naturally transitive: this table belongs to a folder, the folder belongs to a project, this person is a member of a team that owns the project. The decision becomes reachability in a graph of relationships ("is there a path from this person to this object?").
It is the right model when policy is truly hierarchical, which in data platforms is often the case. The cost is architectural. The graph must be replicated and fast. And now a revocation is a write whose visibility is governed by a consistency model (how soon do all copies of the data see an update?). A stale authorization cache is the "read your own writes" problem (you remove a person, then read and still see them) with a security consequence. This is why serious implementations carry explicit consistency tokens on the decision path: a stamp that says "this decision must be based on data at least as new as this change". It is the trade-off between consistency and latency showing up somewhere that does not look like a database.
Policy-as-code: separate decision from enforcement
This is a separate idea that works with all three. It separates the decision point (the component that computes yes or no from policy) from the enforcement point (the component that actually blocks or allows), and it makes the policy a versioned, testable, reviewable file.
Real gain: policy goes through continuous integration and code review, and changes are diffable. Real cost: a security change now has deploy latency, and the split adds a network dependency and a cache on the hot path of every request. Early binding buys testability and pays in agility.
The honest summary
Asking "RBAC or ABAC?" is a category error. Real systems are hybrids: roles carry the coarse grain because roles can be listed and audited, and attributes carry the fine grain because it cannot be listed at all.
Underneath is a general limit: expressiveness and auditability are opposed. Any policy language powerful enough to state your real policy is too powerful to enumerate, so "who can see this?" degrades from a lookup to a search as the model gains power. The same informational limit makes "what is in this dataset?" unanswerable under a late-binding schema without reading the data.
In one sentence: pick the model that matches the shape of your policy matrix, and know that every step up in expressiveness costs you the ability to answer "who can see this?"