Enforcer
Oso Cloud is a hosted authorisation service. You write policies in Polar, Oso's logic language, hold authorisation facts in Oso, and call an API for a decision. There are two evaluation paths. Centralised checks run against facts held in the service, and per Oso's architecture docs the local path works differently: "When you make a request to the Oso Cloud API, you receive back database logic that can be executed against your local data store to finish the authorization evaluation." The same page says "Data that is exclusively or extensively used for authorization, like users, roles, and permissions are best stored in Oso Cloud as facts." Oso does not do authentication, so an identity provider sits alongside it either way. The original self-hosted open source library is a separate product and is deprecated. This page compares the alternatives people actually shortlist, says where Oso is still the right answer, and states where Enforcer is the weaker tool. Every claim below was checked against the vendor's own page or API on 15 September 2026.
Deprecated: See README, and the README opens with a Deprecated heading. Oso is explicit that this is not an end of life. The same README says "we are not end-of-lifing (EOL) the library and we’ll continue to provide support and critical bug fixes." The repo is not archived. The thing to weigh is the distance between that commitment and the commit record: the most recent code commit on main is "Support SQLAlchemy 2.0 with sqlalchemy-oso" on 13 June 2024, and the only push since, on 26 February 2025, was "Update README.md".Stay on Oso Cloud if list filtering at scale is the problem you are genuinely solving. Oso's list filtering docs put the centralised API's optimal range at "Up to ~10,000 authorized resources per user." and the local path's at "Millions of resources per user.", and say the local path suits you when "Users access millions of resources". Be precise about what that establishes. It does not make Oso unique, since SpiceDB and OpenFGA both ship list endpoints, as the table below sets out with their own conditions attached. What it establishes is that Oso has designed for the very large end of it. List filtering only over Enforcer’s own resource types. The engine compiles the same policy into a SQL WHERE clause by partial evaluation, exposed over gRPC as CompileFilter, but only for the eleven types registered in Enforcer’s own process (account, group, tenant, ticket, wallet and six more). There is no REST endpoint for it and no way to register your own tables, so you cannot use it to filter your application’s data. If your product screen is "show me every document this user can read" over your own large table, Enforcer is the wrong tool and you should not shortlist it. Stay also if you already have a working Polar policy in production. Migrating an authorisation model is expensive, and Oso says the open source library is not being end of lifed.
| Option | Model | Strength | Trade-off |
|---|---|---|---|
| SpiceDB (Authzed) | Zanzibar-style relationship database, Apache-2.0, 7,054 stars on 15 September 2026 | Relationship data lives in SpiceDB, and it answers list questions with its own staged guidance. Their FAQ states it in full: "Choose based on your scale: start with LookupResources, move to CheckBulkPermissions when needed, and consider Materialize's Event Streams for the highest performance requirements." The qualifier on the first step is theirs too: of LookupResources the page says "Use when the number of accessible resources is relatively small.", and Materialize Event Streams is marked Early Access. | You mirror your application's relationships into SpiceDB and keep them in sync, which is real, ongoing work. The same FAQ says "SpiceDB is not a policy engine.", so attribute-style and context-dependent rules are awkward to express. It does no authentication. |
| OpenFGA | Zanzibar-inspired authorisation engine, Apache-2.0, 5,773 stars on 15 September 2026 | Two list endpoints, defined by the docs as follows. "A list objects request is a call to the OpenFGA list objects endpoint that returns all objects of a given type that a user has a specified relationship with." and "A list users request is a call to the OpenFGA list users endpoint that returns all users of a given type that have a specified relationship with an object." | The same tuple synchronisation burden as SpiceDB. Attribute logic arrives only through conditions, which the same page defines as "A condition is a function composed of one or more parameters and an expression. Every condition evaluates to a boolean outcome, and expressions are defined using Google's Common Expression Language (CEL).", narrower than a general policy language. It does no authentication. |
| Cerbos | Policy decision point with YAML policies, Apache-2.0, 4,587 stars on 15 September 2026 | Policies are YAML and live in your own storage, and the self-hosted PDP is listed on the pricing page as "Free forever". That free open source tier lists "Audit logs", "CI/CD & IDE tooling" and "Git, Disk, Cloud or DB-based storage" among its features. | The managed control plane is Cerbos Hub, and its free tier is tightly capped: Proof of Concept at "$0/month" lists "1 workspace, 2 developers", "2 simultaneous PDPs" and "1 week of unified audit logs". Past that the page lists Development "From $25/month", Production "From $933/month" and Enterprise. |
| Apache Casbin | Embedded authorisation library, Apache-2.0, 20,389 stars on 15 September 2026 | The largest star count in this list by a wide margin, and it runs in-process across many languages, so there is no network hop on the decision path and no extra service to operate. | It is a library rather than a service, so it is linked into each application and there is no hosted product around it. Anything you want centrally, a shared policy store or a hosted decision surface, you assemble yourself. |
| Ory Keto | Zanzibar-style permission server, Apache-2.0, 5,396 stars on 15 September 2026 | A self-hostable permission server that sits beside Ory Kratos and Hydra if you want identity and permissions from one open source stack. | Relationship tuples again, with the same synchronisation cost. Keto does authorisation only, so authentication means Kratos or Hydra, and adopting it comfortably tends to mean adopting more of the Ory stack than you planned. |
| OPA with OPAL | General policy engine (Rego) plus a policy and data distribution layer, both Apache-2.0 | Decisions stay local to each agent and OPAL keeps them current. OPAL's README describes the mechanism: "OPAL-Servers publish policy and data updates over a lightweight (websocket) PubSub Channel, which OPAL-clients subscribe to via topics." | Two moving parts to run instead of one product. Rego is its own language with its own learning curve, so if a bespoke policy language was your objection to Polar, this relocates the problem rather than solving it. |
Enforcer differs from the products on this page in one way. Identity and authorisation are one service. Enforcer signs the caller in and holds the tenants, roles and groups, so a policy is handed a caller that has already been resolved rather than one asserted on the call, and a decision comes back with a reason and the id of the policy that produced it. Oso does not do authentication, so with Oso you integrate an identity provider as well. Enforcer is itself an MCP server, listed in the MCP registry as dev.instruxi.enforcer/v3 and reachable at https://api.instruxi.dev/mcp.
Where Enforcer is worse, plainly, and what the alternatives do instead. List filtering only over Enforcer’s own resource types. The engine compiles the same policy into a SQL WHERE clause by partial evaluation, exposed over gRPC as CompileFilter, but only for the eleven types registered in Enforcer’s own process (account, group, tenant, ticket, wallet and six more). There is no REST endpoint for it and no way to register your own tables, so you cannot use it to filter your application’s data. It cannot answer "give me every resource this user can read", which is what Oso's local path and the Zanzibar engines above are built for. If that is your requirement, pick one of them. There is no shadow or preview evaluation. An inactive policy is stored and simply not evaluated. Oso is not bare here: Policy Preview, a beta feature, benchmarks the query performance of a candidate policy against your deployed policy using a list of queries you supply in a YAML manifest, and Polar has policy tests. That compares queries you nominate rather than live traffic, so it is not shadow evaluation either, but it is more than Enforcer has. There is no decision log out of the box. GET /audit-events is the identity and admin trail covering logins, API keys, roles, tenants and terms, and it never records authorisation decisions, so logging the returned reason and policy_id is your job. Oso ships the nearest equivalent: its logs page says "Track every authorization check your application sends to Oso Cloud.", viewable at ui.osohq.com/logs, retained for the last 24 hours on Free and Pro and 30+ days with search on Growth, and adds "Log export isn't currently available." Cerbos lists "Audit logs" on its free open source tier. On POST /authz/check the resource is described by the caller and never looked up, so owner_id is an assertion your application must resolve server side. Oso's centralised model reduces that exposure rather than removing it, because the relationship is a fact Oso already holds instead of a claim made on the call, while context facts passed per request are capped (20 on Free, 100 on Startup and Growth, per Oso's rate limits page) and the local path still depends on your application executing the returned logic against correct data. A built-in baseline already allows any action other than manage on a row the caller owns before you write a single rule, and a named policy replaces that built-in decision rather than intersecting with it, which you need to understand before you rely on it. Custom policies are Rego in package enforcer.custom, compiled at write time, capped at 64KB with a 100ms evaluation budget, only a tenant admin can create one, and contexts reaches a named custom policy only. Enforcer is small and new, with no independent reviews and no large community, next to an Oso repo carrying 3,488 stars.
Sources checked 15 September 2026: raw.githubusercontent.com/osohq/oso/main/README. · api.github.com/repos/osohq/oso - description "De · api.github.com/repos/osohq/oso/commits - last co · github.com/osohq/oso/issues/1703 - "Planning the · www.osohq.com/docs/deploy/deployment-models - AW · www.osohq.com/docs/oso-cloud-overview/oso-cloud- · www.osohq.com/docs/develop/enforce/list-filterin · www.osohq.com/docs/develop/troubleshooting/logs · www.osohq.com/docs/develop/policies/policy-previ · www.osohq.com/docs/deploy/account-management/rat · authzed.com/docs/spicedb/getting-started/faq - L · api.github.com/repos/authzed/spicedb - Apache-2.