SpiceDB for Oso users
This document is designed to help teams already using Oso Cloud evaluate SpiceDB: where existing Oso concepts carry over directly, what an AI-assisted migration looks like, and where the two systems genuinely differ.
Migrating from Oso? AuthZed’s spicedb-dev AI agent plugin can convert your schema, relationship
data, application code, and tests automatically. See Build with your AI
agent to get started.
SpiceDB support for Oso features
If you’re already relying on Oso Cloud for the features below, SpiceDB supports the same workflows:
| Oso Cloud feature | SpiceDB equivalent |
|---|---|
| Polar, Oso’s declarative policy language | Schema Language: definitions, relations, and permissions, written and versioned the same way Polar files are |
Built-in RBAC via a resource block’s roles/permissions | A relation for role assignment plus a permission for computed access, the pattern SpiceDB schemas use throughout |
Built-in ReBAC via relations and "role" if "role" on "..." cascades | A relation to another definition plus an arrow (parent->role) that cascades permissions the same way |
authorize, a single yes/no decision | CheckPermission |
actions, listing which actions are available on a resource | CheckBulkPermissions over the candidate actions |
list / authorize_resources, centralized list filtering | LookupResources / CheckBulkPermissions |
Facts (has_role, has_relation, and so on) | Relationships, SpiceDB’s core data primitive |
| Context facts, request-scoped data that isn’t stored | Caveats, evaluated with context passed at check time |
Polar Tests (test "name" { setup { ... } assert allow(...); }) | zed validate with test relationships and assertions |
A global block for org-wide or superadmin roles | A singleton definition referenced by an arrow from every resource, the conventional pattern for platform-wide grants |
How to migrate
Most of the work in migrating off Oso is translating Polar policies and facts into a SpiceDB schema and relationships, not rewriting how your application calls into its authorization layer: the check, list, and write call sites map over directly (see the table above).
AuthZed’s spicedb-dev AI agent plugin automates this kind of migration: converting the schema, the relationship data, the application code, and the tests, then verifying the result with a differential test harness before cutover.
See Build with your AI agent to get AI-assisted help planning and implementing your migration.
Oso concepts and how they map to SpiceDB
| Oso concept | SpiceDB equivalent |
|---|---|
| Actor | Subject |
| Resource | Resource |
A .polar policy file | A .zed schema file |
roles = [...] on a resource block | A relation, written to directly |
permissions = [...] and "x" if "y" shorthand | A permission, computed as a union of relations and other permissions |
relations = { parent: Organization } and "role" if "role" on "parent" | A relation to another definition plus an arrow from it |
Facts (has_role, has_relation, and unary facts) | Relationships: a fact’s subject, predicate, and object become a relationship’s subject, relation, and resource |
not on a fact | The exclusion operator (-) |
The allow rule | No separate override layer: the schema’s permission graph is the authorization logic, so there’s nothing to override |
| Context facts | Caveat context, passed at check time instead of stored |
How SpiceDB is different
A few differences are worth knowing going in, so you can plan for them rather than discover them mid-migration:
- SpiceDB centralizes all of your authorization data in one purpose-built store. Everything a permission decision depends on, stored relationships and caveat context passed with the check, lives in a single, indexed database rather than being split across centralized facts, request context, and your own application database the way it can be in Oso. Bringing data fully into SpiceDB, including structural edges like the
global-block pattern above, gives you one queryable, auditable place to answer “who can access what.” - Consistency is a first-class, explicit choice in SpiceDB. Tunable consistency and ZedTokens let you guarantee a check sees the effects of a prior write, avoiding the New Enemy Problem whenever your workload needs that guarantee.
- Every relation and permission is defined once, in your schema. Because SpiceDB validates relations and permissions against a schema at
WriteSchematime rather than resolving role and permission names as runtime strings, typechecking catches naming drift before it becomes a live authorization bug, and your whole team can find every role and permission your app grants in one file. LookupResourcesgives you filtered results straight from the authorization graph, no SQL to write. Where Oso’slist_localreturns a raw SQL fragment for your app to embed in its own query, SpiceDB answers the same question directly. For the largest, most performance-sensitive filtered lists, AuthZed Materialize extends that same graph into pre-computed, database-native filtering.- SpiceDB is open source, and you choose where it runs. Self-host it yourself, or use AuthZed Cloud as a managed option, with the same schema and API either way.