Comparison with other policy languages
An honest look at CrowdControl next to CEDAR, Cerbos, Rego/OPA, Casbin, XACML, and the Zanzibar family. Every row here exists to help you discard candidates quickly.
Feature matrix
| Feature | CrowdControl | CEDAR | Cerbos | Rego/OPA | Casbin | XACML |
|---|---|---|---|---|---|---|
| Syntax | dedicated DSL | dedicated DSL | YAML + CEL | logic programming | model + CSV/DB | XML |
| Paradigm | rules over a doc | principal/action/resource | resource-scoped | declarative logic | model-driven | attribute-based |
| Input model | single JSON doc | entity graph | principal/resource/aux | any JSON | request tuple | XACML request |
| Turing-complete | no (by design) | no (by design) | no | effectively yes | no | no |
| Formal proofs | no | yes (Lean/Dafny) | no | partial | no | standardized |
| Static type check | opt-in schema | yes | yes | no | no | schema-based |
| Escape clauses | yes | no direct form | via conditions | via negation | via matcher | via obligations |
| Explain mode | yes | yes | yes | yes | no | varies |
| Default deny | opt-in | yes | yes | n/a | n/a | yes |
| Runtime shape | embedded library | lib or service | sidecar/service | sidecar/service | embedded library | big engines |
| External deps | zero | Rust runtime | Go binary | Go binary / WASM | varies | JVM typically |
| Learning curve | minutes | an hour | an afternoon | days | an afternoon | a lifetime |
On "not Turing-complete"
Both CrowdControl and CEDAR list "not Turing-complete" as a feature, not a limitation. Same reasons:
- Bounded evaluation. Every policy terminates in time proportional to the input.
- Decidability. You can answer questions about the policy, not just run it.
- Small surface area. A human can hold the entire language in their head.
Rego made the other trade. It gained recursive rules, comprehensions, partial evaluation, and the ability to express almost any policy you can describe — at the cost of a steeper learning curve and mandatory evaluation timeouts.
CrowdControl could be made Turing-complete by adding recursion, rule references, or user-defined functions. None of those are in the grammar on purpose.
"CEDAR has proofs, CrowdControl has tests"
This phrase gets thrown around a lot. Here's what it actually means.
What CEDAR has
CEDAR has a formal semantics — a mathematical definition of what every policy construct means, written precisely enough that a theorem prover can reason about it. AWS has used Lean and Dafny to prove theorems about CEDAR itself:
- Validator soundness. If CEDAR's type checker accepts your policy, the runtime is mathematically guaranteed never to throw a type error on that policy — for any possible input, not just the ones someone tested.
- Determinism. Same policy + same input always produces the same decision.
- Spec ↔ implementation equivalence. The Rust code you actually run has been proven to match the mathematical spec.
- Analyzer correctness. CEDAR can answer "is policy A strictly more permissive than policy B?" with a proof, not a guess.
These are proofs checked by a theorem prover. They cover every possible input. See cedar-spec.
What CrowdControl has
CrowdControl has a conformance suite — conformance/suite/*.json, every SDK runs it, every SDK must produce identical decisions on every case. Plus unit tests in each port. This gives high confidence for the cases in the suite and nothing for cases outside it.
The practical difference
| Question | CEDAR | CrowdControl |
|---|---|---|
| "Will this policy ever crash at runtime?" | Provably no if it type-checks | Probably not — bounded grammar, covered by tests |
| "Do my Go and Python SDKs agree on all inputs?" | Provably yes | On every input in the conformance suite, yes |
| "Is my new policy strictly stricter than the old one?" | Provably answerable by the analyzer | Enumerate test cases and hope |
| "Can the engine hang on malicious input?" | Provably no | Probably not — but not proven |
If your policy engine serves trillions of authorization decisions for a global cloud provider, the difference matters a lot. If it's gating Terraform plans in CI, a conformance suite you can read in an afternoon is probably the right bar.
CrowdControl vs CEDAR
CEDAR is AWS's open-source policy language, built around a principal/action/resource/context model with an entity store. It's the only production policy language with machine-checked proofs about its semantics.
// CEDAR
permit (
principal in Group::"engineers",
action == Action::"view",
resource in Folder::"public"
);
# CrowdControl
permit "engineers-view-public" {
user.groups contains "engineers"
request.action == "view"
resource.folder == "public"
}
- Data model. CEDAR models a world of entities with attributes and relationships. CrowdControl evaluates a single flat JSON document and has no notion of entities. Structural difference, not a maturity gap.
- Scope. CEDAR answers "can this principal perform this action on this resource?". CrowdControl answers "is this structured document acceptable under these rules?".
- Rigor. CEDAR has machine-checked proofs. CrowdControl has a conformance suite.
You're building fine-grained SaaS authorization with users, groups, roles, and resources — especially if correctness really has to be provable.
You want to gate a plan, a PR, a config file, or any other structured document with rules a security engineer can review on their first day.
CrowdControl vs Cerbos
Cerbos is a stateless policy decision point. Policies are YAML, conditions are CEL, and the engine runs as a sidecar or service next to your app.
# Cerbos
apiVersion: api.cerbos.dev/v1
resourcePolicy:
resource: "album"
rules:
- actions: ["view"]
effect: EFFECT_ALLOW
condition:
match:
expr: "request.resource.attr.public == true"
# CrowdControl
permit "album-view-public" {
request.action == "view"
resource.type == "album"
resource.public == true
}
- Syntax. Cerbos splits into YAML + CEL. CrowdControl is one purpose-built language.
- Deployment. Both ship a deployable PDP now.
cc serveexposesPOST /v1/evaluate, streams structured JSON audit logs, supports shadow mode, and reloads policies atomically on SIGHUP. Cerbos still has more mature rollout controls (percentage rollout, per-rule enable/disable) and richer policy bundle distribution — that's a maturity delta, not a missing capability. - Scope. Cerbos policies are scoped to a resource kind and assume principal/action/resource. CrowdControl rules operate on any document shape.
You need an always-on PDP with production-grade operational surface sitting next to a fleet of microservices, today.
You want something you can call inline from a binary — no service to deploy, no sidecar to babysit.
CrowdControl vs Rego / OPA
Rego is the language of Open Policy Agent. It is a declarative, Datalog-inspired logic language — probably the most powerful policy language in wide production use.
# Rego
package policy
import future.keywords.if
deny contains msg if {
input.user.role == "intern"
input.request.action == "delete"
input.resource.environment == "production"
msg := sprintf("%s is an intern and cannot delete prod", [input.user.name])
}
# CrowdControl
forbid "no-admin-deletes-by-interns" {
user.role == "intern"
request.action == "delete"
resource.environment == "production"
message "{user.name} is an intern and cannot delete prod"
}
- Expressiveness. Rego can express basically any policy you can describe. CrowdControl can't — and won't try. The readability pitch depends on a bounded grammar.
- Learning curve. Rego requires partial rules, comprehensions, unification, and "every rule is a set" thinking. CrowdControl reads like bullet points.
- Tooling. OPA has a huge ecosystem: REPL, Playground, WASM, Gatekeeper, conftest, Styra DAS. CrowdControl has a CLI, LSP, and VS Code extension.
- Debuggability. OPA's trace is a full evaluation tree. CrowdControl's trace is a flat per-condition list with
+/-annotations and resolved values — easier to skim, less powerful.
You need a general-purpose policy engine that scales from admission control to feature flags to data filtering, and the learning curve is worth it.
Your rules are simple enough that the Rego learning curve is the biggest thing standing between "idea" and "rule in CI".
CrowdControl vs Casbin
Casbin is a widely-used authorization library with a model-driven approach — you pick a model (ACL, RBAC, ABAC, RESTful) and provide rules in CSV or a database.
- Indirection. Casbin has a separate model definition file that shapes how policies are interpreted. CrowdControl has no model layer; rules are what they say they are.
- Storage. Casbin is usually backed by a store. CrowdControl loads
.ccfiles at startup. - Scope. Casbin is tightly focused on access control. CrowdControl is a general rule engine for arbitrary JSON documents.
CrowdControl vs XACML
XACML is the OASIS standard for attribute-based access control. It's comprehensive, standardized, and famously verbose.
- Syntax. XACML is XML. CrowdControl is not. This is the entire section.
- Use XACML when: you have a compliance requirement that names XACML.
- Use CrowdControl when: you don't.
Honourable mentions
- SpiceDB / Zanzibar — relationship-based authorization (
document:1#viewer@user:alice). Use it when your questions are "who has access to what, transitively?". CrowdControl has nothing to say about graph traversal. Structural difference. - OpenFGA / Warrant — more Zanzibar-style relationship engines.
- Styra DAS — commercial control plane on top of OPA.
What CrowdControl doesn't have yet
Operational / tooling gaps. None are precluded by the language or engine design.
- Percentage rollout and per-rule enable/disable (whole-server shadow mode exists — see
cc serve) - Signed policy bundle distribution (sign, ship, verify)
- gRPC transport on
cc serve(HTTP+JSON exists) - Rich web playground (planned — see WASM build)
- Formal verification of semantics (CEDAR is the only game in town here)
If any of these are blockers for you, open an issue.
Recently shipped
cc serve— HTTP PDP mode with structured audit logs, shadow mode, SIGHUP reload, bearer-token auth, CORS, and Prometheus metrics.- Docker conformance runners — every SDK ships a
Dockerfileso you can verify it without installing its runtime locally.