SpiceDB Schema Examples
Real authorization schemas, from a starter document sharing model to a full Google Cloud IAM rewrite. Each one is annotated line by line and ready to copy into the SpiceDB Playground.
Basic ReBAC
A starter document/reader/writer schema. The smallest example of Relationship-Based Access Control.
Explore example Groups & hierarchyDocument sharing with groups
Share documents with users, or with groups (which can themselves nest parent / child relationships).
Explore example ABACCaveats (ABAC)
Attribute-Based Access Control with CEL caveats. Conditions evaluated at check time, like IP allowlists or rate limits.
Explore example Real-worldGitHub-style repositories
Models repositories, teams, and organizations with reader / triager / writer / maintainer / admin roles, the way GitHub does it.
Explore example SaaSSaaS entitlements
Per-tier feature flags for a SaaS application. Free and paid plans grant access to different features.
Explore example RBACSuperuser / platform admin
Site-wide super-administrators that inherit access to every resource owned by every organization.
Explore example AdvancedUser-defined roles
Custom roles created at runtime, similar to Jira projects, with built-in roles you can use but not modify.
Explore example Real-worldGoogle Cloud IAM (Spanner)
Re-creates Google Cloud's IAM permissions for Spanner. A large, role-grant-driven schema with cascading project / instance / database scopes.
Explore example AgentsAI agents acting on behalf of users
An AI agent inherits access from the user it acts on behalf of, instead of holding standing permissions of its own.
Explore exampleSpiceDB Schema Fundamentals
On this page
What goes into a SpiceDB schema
A SpiceDB schema declares the object types in your application, the relationships between them, and the permissions those relationships grant. It's how you describe your authorization model in a Zanzibar-style permission system. Four building blocks do most of the work:
definition: an object type.user,document,organization,repository. Subjects and resources are both definitions.relation: a typed link between two objects.writer: usersays "a document can have writers, and they are users." Relations can accept subject sets too, liketeam#member, which means "the members of a team."permission: a computed boolean expressed over relations using union (+), intersection (&), exclusion (-), and arrow (->) operators.permission view = reader + edit: anyone withreaderor anyone who canedit.caveat: a CEL expression evaluated at check time using attributes supplied with the request: time windows, IP allowlists, rate limits. This is how you mix attribute-based logic into relationship-based authorization.
Beyond those four, two operators show up everywhere worth recognizing: subject_type#relation lets a relation reference the result of another relation (subject sets and sub-groups), and the arrow operator relation->permission walks the graph ("the admins of the owning organization").
How to write your first schema
- Start with the resources. List the things in your product users act on: documents, repositories, projects, features. Each becomes a
definition. - Add the subject types. Almost every schema has
definition user {}. If you have groups, teams, or organizations, define those too. - Model the verbs. What can a user do? Read, write, delete, manage billing? Each verb is a
permissionon the resource. - Map verbs to relations. For each permission, decide who has it. Direct readers? Members of the owning organization? Add the relations and compose them with the permission operators.
- Iterate in the playground. Write a few sample relationships and assertions, then refine. The SpiceDB Playground lets you experiment without standing up infrastructure.
Evolving a schema in production
Schemas are not write-once. As your product grows, your authorization model grows with it: new resource types, new roles, new caveats. SpiceDB is designed to make these changes safe.
- Additive changes are free. New definitions, new relations on existing definitions, and new permissions can ship at any time. They don't affect existing checks. Apply with
zed schema writeor theWriteSchemaAPI. - Renames need migration. Renaming a relation breaks existing relationships. Add the new name, dual-write, migrate readers, then remove the old name. The schema evolution guide walks through the pattern.
- Removing a relation is a breaking change. Drop the references in permissions first, then drop the relation. SpiceDB will reject writes that target a non-existent relation, so removing it cuts off new writes immediately while old data lingers until you clean it up.
- Caveats can be added incrementally. A new caveat alongside an existing direct relation keeps the unconditional path working. Turn caveat-required only when you're ready.
- Validation files are your safety net. Pair every schema change with assertions (in YAML next to the schema, just like the examples above) and run them in CI before you deploy. The same files the playground uses are machine-checkable.
Patterns worth knowing
- Subject sets (
team#member): let you grant access to a group of users rather than enumerating them individually. - Wildcard subjects (
user:*): public access without a row per user. - Synthetic relations: a permission used purely as an intermediate computation, like the
project_comment_deleterpermission in the User-defined Roles example. - Arrow for tenancy (
organization->admin): inherit access from a parent object so you don't have to re-grant on every resource. - Exclusion (
-): remove a subject set from a permission ("everyone except billing managers").