Role-based access control works until your product grows sharing: a document shared with a team, inside a folder shared with an organization, with one person blocked. At that point, permissions stop being a table of roles and become a graph of relationships. Google’s Zanzibar paper, published in 2019, described how Google handles that graph for services such as Drive, Calendar, YouTube, and Cloud. This explainer covers how Zanzibar works and how its two best-known open-source descendants, SpiceDB and OpenFGA, bring the model to everyone else.
At a Glance
| Spec | Detail |
| What Zanzibar is | Google’s global system for storing and evaluating access control lists |
| Published | USENIX Annual Technical Conference (ATC ’19), 2019 |
| Model | Relationship-based access control (ReBAC) built on relation tuples |
| Scale reported in the paper | 2+ trillion relation tuples, 10+ million client queries per second, 95th-percentile latency under 10 ms, availability above 99.999% over 3 years |
| Open-source implementations | SpiceDB (Apache-2.0) and OpenFGA (Apache-2.0, a CNCF project) |
| Best for | Products with sharing, nested groups, and hierarchies of resources |
Short Verdict
If your permission rules sound like “anyone who can view the parent folder can view this file” or “members of a team inherit the team’s access,” a Zanzibar-style system models them directly instead of through ever-growing role tables. You do not need Google’s scale to benefit: SpiceDB and OpenFGA give you the data model and APIs as open source. The cost is a new piece of infrastructure to run and keep in sync with your application data, so simple apps with a handful of fixed roles are still better off with plain RBAC.
The Data Model: Relation Tuples
Zanzibar stores every permission fact as a relation tuple written object#relation@user. The paper’s example doc:readme#owner@10 means user 10 is an owner of the document readme. Objects are written namespace:object_id, and the “user” side can be either a user ID or a userset, which is another object#relation pair. That is what makes nested groups possible: a tuple can say “members of group X are viewers of this document,” and group membership is itself stored as tuples.
Each client defines a namespace configuration that lists its relations, such as owner, editor, and viewer, and optional userset rewrite rules that derive access instead of storing it. The paper describes three building blocks: _this (users stored directly on the relation), computed_userset (for example, every owner is also an editor, and every editor is also a viewer), and tuple_to_userset (for example, viewers of a document’s parent folder can view the document). These combine with union, intersection, and exclusion, which is how one small configuration expresses an entire permission hierarchy.
The APIs
| API | What it does |
|---|---|
| Check | Answers “does this user have this relation to this object?” at a sufficiently fresh snapshot |
| Read | Returns stored tuples matching a filter, without applying rewrite rules |
| Write | Adds or removes tuples, with optimistic concurrency for read-modify-write |
| Watch | Streams tuple changes in timestamp order, so other systems can stay in sync |
| Expand | Returns the full effective userset as a tree, useful for building search indexes |
The Hard Part: The “New Enemy” Problem and Zookies
One of the paper’s central ideas is how it keeps authorization consistent with content. Its example: Alice removes Bob from a folder, then adds new documents to it. If the system evaluates Bob’s access against an old copy of the permissions, Bob could see documents he should never see. Zanzibar calls this the “new enemy” problem. It solves it with external consistency built on Google Spanner’s timestamps, plus an opaque token called a zookie. When content changes, the client asks Zanzibar for a zookie encoding the current time and stores it with the content. Later checks send that zookie, guaranteeing evaluation against permissions at least that fresh, while most checks can still be answered quickly from nearby replicas.
For deeply nested groups, where following pointers one hop at a time gets slow, the paper describes a specialized index called Leopard that precomputes group-to-group and member-to-group sets so membership becomes a set intersection.
SpiceDB vs OpenFGA
| SpiceDB | OpenFGA | |
|---|---|---|
| Relationship to Zanzibar | Describes itself as the most mature open-source project inspired by Zanzibar; aims to stay true to the paper | Inspired by Zanzibar; ReBAC that can also express RBAC and some ABAC |
| License | Apache-2.0 | Apache-2.0 |
| Governance | Created by AuthZed; open-sourced September 2021 | Owned by the Cloud Native Computing Foundation |
| Modeling | Schema language defining object types, relations, and permissions | Authorization models built from type definitions and relationship tuples |
| Consistency | Configurable per request, designed to prevent the new enemy problem | Supports contextual tuples supplied per request |
| Conditions / attributes | See SpiceDB docs | Conditional relationship tuples using CEL expressions |
| Storage | Pluggable: in-memory, Spanner, CockroachDB, PostgreSQL, MySQL | See OpenFGA docs for supported datastores |
Pros
Permissions live in one service with one model, instead of being re-implemented in every microservice. Sharing, nested teams, and resource hierarchies are expressed directly rather than through role explosion. The Check API gives every service the same answer, and Watch-style change streams let search indexes respect permissions. Both leading implementations are permissively licensed open source.
Cons
It is another critical, latency-sensitive service to operate, and an outage blocks every access decision. Your application must write relationship tuples whenever ownership or membership changes, and drift between app data and authorization data becomes a new class of bug. Consistency tokens add complexity that teams need to understand to use correctly. For a small app with a few fixed roles, this is more machinery than the problem requires.
Bottom Line
Zanzibar showed that a single relationship-based model can cover permissions for products used by billions of people while staying fast and consistent. If your product has sharing and hierarchies, its model is worth adopting through SpiceDB or OpenFGA; prototype your permission rules in either tool’s schema and see whether they read more clearly than your current role checks. If they do not, plain RBAC is still fine.
Frequently Asked Questions
- Is Zanzibar available to use? Zanzibar itself is internal to Google; SpiceDB and OpenFGA are open-source systems inspired by its paper.
- What is a relation tuple? A stored fact of the form
object#relation@user, such as “user 10 is an owner of doc readme.” - What is the new enemy problem? Evaluating access against stale permissions, so a removed user can see content added after the removal. Zanzibar prevents it with consistency tokens called zookies.
- Is ReBAC a replacement for RBAC? It is a superset: roles can be modeled as relations, and OpenFGA notes its model can express RBAC and some ABAC scenarios.
