Skip to content

Execution cost#

CEL runtimes can estimate the computational cost of expressions. Cost analysis helps prevent denial-of-service through expensive expressions.

Why cost matters#

Some CEL applications allow users to submit expressions. Without limits, a poorly-written or even malicious expression could:

  • Consume excessive CPU time
  • Allocate large amounts of memory
  • Cause timeouts or service degradation
// input: large_list = [1, 2, 3, ...]
large_list.map(x, x * x).filter(x, x > 0).size()

Static vs dynamic cost#

CEL provides utilities for estimating and tracking the cost of the expressions it evaluates. Cost is divided into two categories:

  • Static cost is estimated at compile time based on the expression structure. It provides an upper bound but overestimates for macros and conditional branches without size estimates for input variables.
  • Dynamic cost is tracked during evaluation. It reflects the actual operations performed. Dynamic cost is useful for runtime limits because it measures real work done.

Static cost model#

CEL assigns costs to operations for static analysis. The following values are from cel-go; other runtimes may differ.

Operation Cost
Scalar literals 0
List literals 10 + cost of each element
Map literals 30 + cost of each key and value
Message literals 40 + cost of each field value
Variable access 1
Operators 1
Function calls 1 + cost of each argument (default)
String functions string length x 0.1
Regex functions string length x pattern length x 0.25
Macros collection size x predicate cost(s)
Conditional condition + max(true branch, false branch)

The total cost is estimated by summing operation costs.

Setting limits#

Set dynamic cost limits to terminate expensive expressions:

// Pseudocode - syntax varies by runtime
expression.Eval(input, CostLimit(1000))

Exceeding the limit short-circuits execution and produces a runtime error.

Custom function costs#

When defining custom functions and macros, assign appropriate costs. Expensive operations (network calls, cryptography) should have high costs.

Runtime specifics#

Cost analysis implementation varies by runtime:

  • cel-go: Use cel.CostTracking() and cel.CostLimit()
  • cel-java: Use CelRuntime.CostTracker
  • cel-cpp: Use CostTracker

See also#