Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/spicedb/getting-started/coming-from/_meta.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
opa: "Open Policy Agent",
cancancan: "Ruby on Rails",
oso: "Oso",
};
66 changes: 66 additions & 0 deletions app/spicedb/getting-started/coming-from/oso/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: "SpiceDB for Oso users"
description: "How SpiceDB compares to Oso Cloud: feature-by-feature support, an AI-assisted migration path, and how Oso's concepts map onto SpiceDB."
---

import { Callout } from "nextra/components";

# 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.

<Callout type="info">
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](/spicedb/getting-started/build-with-an-agent#migrating-to-spicedb) to get started.
</Callout>

## 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](/spicedb/concepts/schema): 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](/spicedb/concepts/schema#--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](/spicedb/concepts/caveats), evaluated with context passed at check time |
| Polar Tests (`test "name" { setup { ... } assert allow(...); }`) | [`zed validate`](/spicedb/modeling/validation-testing-debugging#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](/spicedb/getting-started/build-with-an-agent#migrating-to-spicedb) 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](/spicedb/concepts/schema#--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](/spicedb/concepts/consistency) and ZedTokens let you guarantee a check sees the effects of a prior write, avoiding the [New Enemy Problem](/spicedb/concepts/zanzibar#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 `WriteSchema` time rather than resolving role and permission names as runtime strings, [typechecking](/spicedb/concepts/schema#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.
- **`LookupResources` gives you filtered results straight from the authorization graph, no SQL to write.** Where Oso's `list_local` returns 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](https://authzed.com/products/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](https://authzed.com/cloud) as a managed option, with the same schema and API either way.
Loading