Cerbos: A Self-Hosted Policy Decision Point for YAML Authorization
Cerbos is an open-core authorization management platform for authorizing every identity and governing every action across applications, gateways, workloads, and AI agents.
At a glance
- What is it?
- Cerbos splits authorization decisions out of your application into a stateless Go service that evaluates YAML policies. It fits teams who need context-aware rules and can run and feed another process; it is the wrong tool if you cannot operate that process or cannot describe your rules in policy files.
- Who is it for?
- Adopt Cerbos if you already run Go services, want authorization decisions expressed as reviewable YAML in Git, and can operate a stateless PDP next to your workload. Do not adopt it if you cannot run or reach another process on the request path, or if your rules are simple enough that a library call inside your own binary suffices.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Problem Cerbos Moves Out of Your Application Code
Most applications start with permission checks scattered through handlers: a role comparison here, an owner check there, a special case for the admin who also happens to be the account owner. The README frames the alternative as an authorization layer where rules live in YAML policies managed through Git-ops, evaluated by a separate Policy Decision Point. The intended audience is a team that has outgrown role checks and now needs conditions on attributes, not just role membership. The README describes the progression directly: if simple RBAC does not cut it, conditions in resource policies are evaluated at runtime using contextual data, derived roles extend RBAC roles dynamically, and principal policies provide overrides for a specific user. That is a real distinction. A role check can live in a middleware function. A rule that says a user may view a resource when request.resource.attr.public is true, unless a principal policy says otherwise, is a decision that benefits from a single evaluation point and a file that a reviewer can read. The cost is architectural: the decision now happens somewhere else.
Principals, Actions, Resources, and the Two APIs
The README defines four concepts. A principal is the thing attempting an action, described as often just the user but also applications, services, or bots. An action is a specific task such as create, view, update, or delete. A resource is what access is being controlled, defined by writing policies. Policies are YAML files holding the rules for each resource. The PDP itself is described as a stateless service where policies are executed and decisions are made. It exposes two APIs. CheckResources answers whether a principal can access a resource. PlanResources answers which resources of a given kind a principal can access, and the README notes a set of query plan adapters that convert PlanResources responses into a query instance for a datastore. That second API is the more interesting one. CheckResources is a boolean-shaped question you could answer with a function call. PlanResources exists because filtering a list is a different problem from permitting a single object, and pushing that filtering down to the database avoids loading rows the principal may not see. If your application only ever checks one object at a time, you are using roughly half of what the PDP offers.
Storage Drivers Decide How Policies Reach the PDP
Policies are stored on disk, in cloud object stores, in git repositories, or dynamically in supported databases, and the README says these are continually monitored by the PDP. That monitoring is the mechanism behind policy updates without a restart, and it is also where deployment choices become concrete. A disk driver means the policy directory must be present in the container or on the host, which usually means a volume mount or a baked image. A git driver means the PDP polls a repository, which fits the Git-ops workflow the README advertises but adds a network dependency and a polling interval between a merge and a decision changing. A blob driver points at object storage. The database option is listed for dynamic storage. The trade-off is not stated in the README, so treat it as something to test: the further the policy source is from the process, the more failure modes sit between a policy edit and the decision your application receives. A sidecar deployment, which the README lists alongside a Kubernetes service, systemd service, and AWS Lambda function, narrows that gap by putting the PDP in the same pod as the workload.
Getting a PDP Running
The README points to three installation routes: a container image, binary or OS packages, and a Helm chart. It also gives a resource policy example. The policy declares apiVersion: api.cerbos.dev/v1, a resourcePolicy block with importDerivedRoles referencing common_roles, a resource of album:object, a version of default, and a rules list. The first rule allows all actions to a derived role named owner. The second allows the view and flag actions to the user role but only when request.resource.attr.public == true, expressed under condition.match.expr. The README's example is truncated mid-rule, so the full set of rule shapes is not visible here; the documentation is the place to confirm effect values and condition syntax. The README also shows that the APIs can be called with cURL, which is the fastest way to confirm a PDP is answering before you wire an SDK into an application. Client SDKs exist for production use, and the README says the list is in the repository. Nothing in the supplied material gives a run command, a configuration file key, or a port number, so those must come from the installation documentation rather than from this review.
The Open-Core Boundary Is the Real Adoption Question
This repository contains what you need for a self-hosted PDP, and the README is explicit about that. Cerbos Hub is a separate cloud-hosted control plane offering collaborative policy playgrounds, distribution of policy updates to a PDP fleet, policy bundles for client-side or in-browser authorization, and an Embedded PDP for serverless and edge deployments. The README also notes that Hub streamlines policy authoring and distribution to self-hosted PDPs. The boundary matters because some of the workflow conveniences sit on the paid side. Distributing policy updates to a fleet, for example, is something you can build yourself on top of the git or blob drivers, but the README presents the managed version as the Hub feature. If your team is small and your policy count is low, the self-hosted path is complete on its own. If you expect many PDP instances and frequent policy changes, read the Hub feature list carefully before assuming the open repository covers your distribution needs. The licence on this repository is Apache-2.0, which is permissive, but the Hub component is a separate product and its terms are not described in the supplied material. That is a question for the vendor, not something to infer from the repository licence.
Where a Separate Decision Point Hurts
The clearest limitation is the one the architecture implies: every authorization decision becomes a network call unless you embed the PDP as a sidecar or run it in-process. The README lists sidecar and Lambda deployments, which suggests the project takes this seriously, but the default described shape is a separate service. On a request path where latency budgets are tight, adding a hop to every check is a cost you have to justify. There is a second constraint. Policies are YAML files in a Git-ops flow, which is excellent for review and terrible for data that changes per user. If your access rules depend on values that live in your application database and change constantly, you either feed those values into the request as contextual attributes or you fight the model. The README's condition example reads request.resource.attr.public, which is exactly the pattern: the attribute travels with the request rather than being looked up by the PDP. That means the calling application still has to assemble the context correctly, and a missing attribute is a policy evaluation problem, not a database problem. Cerbos is also the wrong tool when your rules are genuinely simple. If a single role column answers every question in your system, a PDP adds a process, a policy directory, and a deployment surface for no decision that a middleware could not make.
How This Differs from an Embedded Authorization Library
The realistic alternative is an authorization library that runs inside your own process, evaluating rules you define in your application's language. The difference in approach is where the decision executes and who owns the policy format. An embedded library keeps the check in-process, so there is no hop and no separate deployment; the rules are code or configuration in your repository, versioned with your application. Cerbos moves the decision to a stateless service and standardizes the rules as YAML with its own schema, apiVersion: api.cerbos.dev/v1, so the same policy can be evaluated by a PDP running as a Kubernetes service, a sidecar, a systemd unit, or a Lambda function. That portability is the point. A policy file is not tied to one service's language, which matters when several services written in different languages need to answer the same access question consistently. The embedded library wins on latency and operational simplicity. Cerbos wins when the same rules must be enforced across multiple services, when you want policy changes to be reviewed and deployed independently of application releases, and when you need the PlanResources style of query planning to filter collections at the datastore rather than in memory.
Maintenance and Upgrade Cost
The release history shows a steady cadence: v0.55.0 in August 2026, v0.54.0 in July 2026, v0.53.0 in May 2026. That is roughly monthly to bi-monthly, and the version numbers are still below 1.0, which is worth weighing. Pre-1.0 projects can change policy schema or configuration between minor releases, and the README does not describe a compatibility policy. The practical implication is that you should pin the PDP image or package version and read the release notes before moving, rather than tracking latest. Policy files are the durable asset here, not the binary, so the migration question is whether a policy written against one version still evaluates the same way on the next. The repository is Apache-2.0, which permits commercial use and modification, but that licence covers this repository only. Anything you adopt from Cerbos Hub carries its own terms, and the supplied material does not state them. Confirm the licence and support terms for the Hub components separately if your deployment depends on them.
Editorial conclusion
Adopt Cerbos if you already run Go services, want authorization decisions expressed as reviewable YAML in Git, and can operate a stateless PDP next to your workload. Do not adopt it if you cannot run or reach another process on the request path, or if your rules are simple enough that a library call inside your own binary suffices. Before committing, verify three things against your own policies: that the storage driver you intend to use (disk, blob, git, or database) is the one your deployment can actually write to, that the PlanResources query plan adapters cover your datastore, and that the open-core split between this repository and Cerbos Hub matches the features you need.
Community notes