Risor vs CEL

CEL (Common Expression Language) is Google's expression language for policy and configuration. It's safe, fast, and standardized across Go, C++, Java, Rust, Python, and TypeScript. You'll find it in Kubernetes admission controllers, Google Cloud IAM, Firebase security rules, and Envoy.

CEL evaluates single expressions. When you need variables, multi-step computation, or functions, you need a scripting language.

Simple Conditions

Both handle single expressions the same way:

request.auth.claims.role == "admin"
    || (resource.classification == "public"
        && request.method in ["GET", "HEAD"])

Multi-step Logic

CEL requires chaining separate evaluations with host code bridging them:

// Expression 1: calculate discount tier
account.total_spend > 10000 ? 0.20 : account.total_spend > 5000 ? 0.10 : 0.05

// Expression 2: host injects tier from expression 1
line_items.map(i, i.price * i.quantity).sum() * (1.0 - discount_tier)

Risor handles it in one script:

let tier = if (account.total_spend > 10000) { 0.20 }
    else if (account.total_spend > 5000) { 0.10 }
    else { 0.05 }
 
let subtotal = line_items.map(i => i.price * i.quantity) |> math.sum
subtotal * (1 - tier)

Comparison

PropertyCELRisor
ScopeSingle expressionsMulti-statement scripts
Variables / functionsNoYes
Pattern matching / pipesNoYes
SandboxedYesYes (empty by default)
Type systemProtobuf-centricNative host types
SyntaxC-likeTypeScript-like
Feature controlFixedHost chooses which features to enable
Cross-languageGo, C++, Java, Rust, Python, TSGo (Rust and TS planned)

Performance

CEL is fast at what it does. On a simple conditional, CEL evaluates in 0.08 µs versus Risor's 15.2 µs. Its flat evaluation tree has almost zero runtime overhead.

But CEL can only evaluate single expressions. It has no reduce, no sum, no variables. Our benchmark suite includes two harder scenarios (filtering 10,000 records, and a multi-step business logic pipeline) and CEL can't participate in either. The host would need to loop over results in Go code.

On memory, Risor is smaller: 2.2 KB per compiled instance versus CEL's 23.1 KB (10.5×). CEL carries protobuf type metadata.

ScenarioCELRisor
Simple expression (warm)0.08 µs15.2 µs
Data processing (10k records)N/A4.20 ms
Business logic (500 records)N/A273 µs
Heap per instance (simple)23.1 KB2.2 KB

When to Choose CEL

  • Your logic fits in a single expression
  • You're in the Kubernetes ecosystem
  • You need cross-language evaluation with protobuf types

When to Choose Risor

  • You need variables, conditionals, or multi-step computation
  • You want TypeScript-like syntax and native host types
  • You want the host to control which language features are available

Learn More


Risor © 2026 Deep Noodle