How Google Checks Access Permissions for Billions of Users and What SpiceDB Has to Do With It
When a project outgrows a simple scheme with admin and user roles, chaos begins. In a microservices architecture, permission checking often turns into a tangled web. One service stores roles in a database, another validates JWT tokens, a third runs heavy SQL queries with a dozen JOINs. Since 2021, OWASP has been calling access control failures (Broken Access Control) the number one threat to web application security.
Google faced this problem many years ago. For Google Drive, YouTube, and Cloud IAM, the company developed a unified centralized authorization system called Zanzibar. In 2019, engineers published a paper describing its architecture, and the Authzed team took this idea and created SpiceDB — an open-source database for access control management.
Why Move Authorization to a Separate Database
Regular databases are good at storing business entities, but they struggle with complex permission graphs. Imagine a document sitting in a folder that is inside another folder, shared with a group of users that includes a separate company department. Calculating whether a specific employee has access to the file becomes painful and slow using a standard DBMS.
SpiceDB takes this task off your hands. You send a simple query to the database: "Can user X perform action Y on resource Z?". The response is a fast binary answer.
At the same time, SpiceDB handles only authorization (access permissions) and knows nothing about authentication (identity verification). Checking passwords, logging in users, and issuing tokens should still be handled by your identity provider like Keycloak or Auth0.
How the Schema and Relationship Language Works
Working with SpiceDB starts with describing a schema. The schema defines object types and rules for computing permissions.
The schema syntax looks readable and concise:
definition user {}
definition folder {
relation parent: folder
relation viewer: user
permission view = viewer + parent->view
}
definition document {
relation folder: folder
relation viewer: user
permission view = viewer + folder->view
}
In this example, access view to a document is automatically granted to users listed directly in viewer, as well as those who have permission view on the parent folder. The nesting chain can be of any depth.
The actual data is stored as relationships. These are simple facts about the system, for example:
folder:finance— an object of type folder with IDfinanceviewer— a relationuser:mikhail— a subject
Recording such a relationship means that Mikhail became a reader of the finance folder.
ReBAC and Attributes: Netflix's Experience
Unlike classic RBAC (Role-Based Access Control), SpiceDB implements ReBAC (Relationship-Based Access Control). Access is determined through relationships between objects in a graph.
But sometimes businesses need more than just knowing that a user is part of a team. They need to check a contextual condition: for example, that the person is accessing from a corporate IP address or that the request was made during business hours.
For such scenarios, Netflix engineers helped add a caveats mechanism to SpiceDB. This combines ReBAC and ABAC (Attribute-Based Access Control). A contextual function is attached to a relationship, calculated at the moment of permission checking.
Architecture and Performance Under Load
SpiceDB is written in Go and designed for high loads. The authors claim 5ms latency at p95 with millions of queries per second and billions of relationships in the database.
As storage (datastores), you can connect familiar DBMSs:
- PostgreSQL
- CockroachDB
- MySQL (the driver for MySQL was written by GitHub's authorization team)
- Google Cloud Spanner
One interesting feature is consistency management at the individual query level. If a user just changed access permissions and wants to see the result immediately, the application sends a request requiring fully consistent data. However, if we're rendering a public catalog where a couple of seconds of delay is not critical, we allow caching and reduce load on the database.
SpiceDB can also answer "reverse" questions: "What resources does the user have access to?" or "Who can view this document?". For this, it uses reverse indexes internally.
Quick Start with Docker and curl
You can spin up SpiceDB for experiments with a single Docker command:
docker run --rm -p 50051:50051 -p 8443:8443 \
authzed/spicedb serve \
--http-enabled true \
--grpc-preshared-key "somerandomkeyhere"
After startup, load the schema via the HTTP API:
curl --location 'http://localhost:8443/v1/schema/write' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer somerandomkeyhere' \
--data '{
"schema": "definition user {} \n definition folder { \n relation viewer: user \n permission view = viewer \n }"
}'
Add a relationship stating that user anne can view folder budget:
curl --location 'http://localhost:8443/v1/relationships/write' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer somerandomkeyhere' \
--data '{
"updates": [
{
"operation": "OPERATION_TOUCH",
"relationship": {
"resource": { "objectType": "folder", "objectId": "budget" },
"relation": "viewer",
"subject": { "object": { "objectType": "user", "objectId": "anne" } }
}
}
]
}'
Now check the permissions:
curl --location 'http://localhost:8443/v1/permissions/check' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer somerandomkeyhere' \
--data '{
"resource": { "objectType": "folder", "objectId": "budget" },
"permission": "view",
"subject": { "object": { "objectType": "user", "objectId": "anne" } }
}'
We'll receive status PERMISSIONSHIP_HAS_PERMISSION in response.
In addition to REST and gRPC APIs, the developers offer a command-line utility zed and a browser-based sandbox called Playground (play.authzed.com). It's convenient for sketching out a permission model, populating it with test data, and testing hypotheses before writing any code.
Who This Tool Is For
SpiceDB is already running in production at Red Hat, IBM, GitPod, and Tubi.
Introducing such a system in a small monolith where all permissions are limited to an admin panel and a couple of roles makes little sense — it's unnecessary infrastructure complexity. However, the tool is perfect when:
- You have a dozen microservices, and each tries to check permissions in its own way.
- Your product logic requires file sharing, complex folder hierarchies, or team accounts.
- You need a security audit and a single point of access control management.
For deployment in Kubernetes, Authzed provides an official operator. The project is actively developing, and the GitHub repository already has nearly 7,000 stars.
相关项目