OPA vs Cedar: policy engines compared for application authorisation
Open Policy Agent (Rego) vs Cedar: language design, analysis, performance and where each fits, from Kubernetes admission to app permissions.
OPA is a general purpose policy engine: Rego can evaluate any JSON and return any shape of answer, which makes it the standard for infrastructure policy such as Kubernetes admission, Terraform checks and service mesh authorisation. Cedar is purpose-built for application authorisation: principal, action, resource, with permit and forbid rules, a schema and formal analysis. Pick Cedar for fine-grained permissions inside your product, OPA for guardrails across your platform. Using both in one organisation is normal.
| OPA | Cedar | |
|---|---|---|
| Origin | Styra, CNCF graduated project | AWS, open source since 2023 |
| Language | Rego, Datalog-inspired, general purpose | Cedar, authorisation-specific |
| Input | Arbitrary JSON input and data documents | Principal, action, resource, context, entities |
| Output | Any JSON: booleans, lists of violations, objects | Allow or deny plus the policies that decided it |
| Conflict rule | Whatever you write; default value if undefined | Default deny; any forbid overrides any permit |
| Schema | Optional (JSON Schema annotations) | Schema validation built in |
| Analysis | Tests, coverage, partial evaluation | Validation, formal verification, SMT-based policy analysis |
| Implementation | Go, library or daemon, Wasm compile target | Rust core, bindings for other languages |
| Distribution | Bundles and decision logs | Your own store or Amazon Verified Permissions |
| Sweet spot | Kubernetes, CI, Envoy, cloud guardrails | In-app RBAC, ABAC and hierarchy permissions |
01How each one works
OPA evaluates Rego rules against an input document (the request) and a data document (loaded facts). Rules are queries: a rule is true if all its expressions hold for some binding of variables, and you can generate sets, objects and messages. OPA has no built-in notion of users or resources; you model everything. Since OPA 1.0, Rego v1 syntax with if and contains is the default.
Cedar evaluates permit and forbid policies over a request of principal, action, resource and context, plus an entity store with attributes and parent relationships. The language is deliberately limited (no loops, no arbitrary recursion) so it always terminates, can be validated against a schema, and can be analysed to answer questions such as whether two policy sets allow the same requests.
Rego can express almost anything, which is why it fits infrastructure policy. Cedar gives up generality to gain predictability, which is what you want for permissions you must prove correct.
02The same policy in both
Rule: a user can view a document they own or one from their department, but nobody can view an archived document.
package docs.authz
default allow := false
allow if {
input.action == "view"
not input.resource.archived
input.resource.owner == input.principal.id
}
allow if {
input.action == "view"
not input.resource.archived
input.resource.department == input.principal.department
}permit (
principal,
action == Action::"view",
resource is Document
)
when { resource.owner == principal };
permit (
principal is User,
action == Action::"view",
resource is Document
)
when { resource.department == principal.department };
forbid (principal, action, resource is Document)
when { resource.archived };Note the difference in how the exception is expressed. In Rego the archived check has to be repeated in every allow rule, or factored into a helper. In Cedar a single forbid overrides every permit, so a new permit added later cannot accidentally reopen archived documents.
03When to pick which
- Kubernetes admission, Terraform plans, CI config checks or Envoy ext_authz: OPA, with Gatekeeper or conftest. The ecosystem is there and the output is often a list of violations, not a yes or no.
- Fine-grained permissions in your own application, especially multi-tenant SaaS: Cedar. The principal, action, resource model and forbid-wins semantics match the problem.
- You need to prove properties of policy changes, such as a refactor allowing nothing new: Cedar's analysis tooling is built for this.
- Large relationship graphs (Google Docs style sharing at scale): neither alone. Cedar needs the relevant entities passed in with each request; consider a Zanzibar-style ReBAC system and use Cedar or OPA for the attribute rules on top.
- Data filtering (which rows can this user see): OPA partial evaluation can compile policy into query conditions; Cedar's equivalent is less mature.
04Common mistakes and migration notes
- Rego: writing rules that are undefined rather than false and forgetting a default. Always set default allow := false.
- Rego: mixing pre-1.0 syntax (no if, no contains) with OPA 1.x. Run opa fmt and opa check, or the rego.v1 import on older versions.
- Cedar: expecting policies to fetch data. Cedar evaluates only the entities you supply, so your app must load the principal, resource and their parents first.
- Both: putting the engine on the network path for every request without caching or a local sidecar. Authorisation latency adds to every call.
- Migrating Rego to Cedar: translate deny rules into forbid policies and let them stand alone, rather than folding conditions into every permit.
Whichever engine you choose, log the inputs and decision for every evaluation (with secrets redacted). Without decision logs you cannot answer who could access what, which is the first question in an incident.
05How to say it in an interview
"OPA is a general engine: Rego over any JSON, any output, which is why it owns Kubernetes admission and infrastructure guardrails. Cedar is narrow on purpose: principal, action, resource, default deny and forbid wins, with schema validation and formal analysis. I'd use Cedar for product permissions where I need to prove a change is safe, and OPA for platform policy."
Questions people ask
Q1Is Cedar faster than OPA?+
For simple authorisation checks both evaluate in microseconds to low milliseconds. Cedar's restricted language makes its performance more predictable; OPA's speed depends heavily on how the Rego is written and how much data is loaded.
Q2Can Cedar be used outside AWS?+
Yes. Cedar is open source under Apache 2.0 with a Rust implementation and language bindings, and runs anywhere. Amazon Verified Permissions is a managed service built on it.
Q3Can OPA do RBAC and ABAC?+
Yes. Roles, attributes and relationships are just data and input documents in OPA. You write the logic yourself, which is flexible but means more to test.
Q4What is Rego v1?+
The syntax made default in OPA 1.0 (December 2024). It requires the if keyword for rule bodies and contains for multi-value rules, removing ambiguities in the older syntax.
Q5Should I use OPA Gatekeeper or Kyverno instead?+
For Kubernetes only, Kyverno uses YAML policies and is easier for many teams; Gatekeeper uses Rego and shares skills with the rest of OPA. Cedar is not a Kubernetes admission tool.
Go deeper
- Authorisation models: RBAC, ABAC, ReBACSecEng · Identity & Access EngineeringPro
- Design an authorisation engine (RBAC + ABAC)LLD · Problems: Access controlFree
- Design a Kubernetes admission control serviceHLD · Design problems: cloud & runtime securityPro
- Cloud guardrails and posture managementSecEng · Cloud & Platform SecurityPro