Want to express "the rules" of your system without wiring up a whole new microservice or custom program for each situation? CEL is for you.

I was travelling with my brother in Europe way back, another lifetime ago. We had a total of two CDs in the car: U2's Zooropa and Woodface by Crowded House. So there's your timestamp. We passed some graffiti on a wall somewhere... maybe it was Switzerland, I can't remember... and it said "Do you follow the rules?" Something about that most masterful placement of the article "the" made the phrase stick in memory…

At any rate, I was working on a CEL implementation for SimpleValidations today, and that image came back to me. As you know, SimpleValidations is this data validation site I'm building, and it's all about "the rules," or at least allowing authors to define the rules by which user data is validated. Turns out CEL is a great little tool that can help authors describe very easily some of the validations they want to apply to incoming data.

So what's CEL? CEL, or Common Expression Language, is a small, safe expression language for evaluating boolean logic and simple math over your data. It's good for writing expressions that evaluate to values — most often booleans for "policy" or "validation" checks. Think something like:

p95(temp) <= 298.15 && all(rooms, r, r.vent_ok)

CEL looks like a simplified blend of JavaScript and Python. It has:

  • familiar operators: &&, ||, !, <=, in
  • first-class lists and maps
  • a small, safe standard library (and you can add your own pure functions)
  • variables ("bindings") provided by the host app

It’s intentionally not a general programming language. No loops, no side effects. That keeps it safe in production and easy to reason about.

You’ll find CEL anywhere teams want policy-as-data: API gateways, config validators, and data quality tools. And because CEL is embeddable, the application decides which functions and names exist. You get the flexibility of runtime rules with the safety of a closed sandbox.

A few common use cases might be:

  • API authorization & policy engines: write allow/deny rules that read request attributes and return a boolean.
  • Configuration validation: ensure a config or payload meets business constraints with friendly fail messages.
  • Data quality checks: compute small metrics and assert ranges/relationships between them.

So you can probably start to see why this is useful for SimpleValidations, where authors are defining validation rules for different domains and different "engines" that produce downstream data, like EnergyPlus or Modelica simulations CEL is used to help these authors describe "what good looks like" without having to provide actual Python code.

Some Example CEL Checks

Intrigued? Here's an example use case. Let's assume our author is using CEL to define some validation checks for EnergyPlus files submitted by a user. SimpleValidations handles running this file through E+, collecting the output, and then applying the author's checks against the data.

SimpleValidations gives the author access to "signals" which relate to input or output variables, and the author can use those signal names to link the data they represent to helper functions that perform operations as part of a check. For example, the following are available to the author:

  • floor_area_m2: a decimal value representing the floor area of the model
  • eui_kwh_m2_yr: an Energy Use Intensity value from E+ output
  • lighting_W: a time series for the 'Lights Electric Power' data from E+ output.
  • Helper functions:
    • p(values, q) → percentile (e.g., p(x, 0.95) for p95)
    • mean(values) → average
    • has(x) → value is present

Given those, here are some simple checks the author could define:

1) A basic check
mean(lighting_W) / floor_area_m2 <= 12

"Average lighting power density is ≤ 12 W/m²."

2) EUI band (annual, site)
is_number(eui_kwh_m2_yr) && eui_kwh_m2_yr >= 50 && eui_kwh_m2_yr <= 120

“Keep whole-building site EUI between 50–120 kWh/m²·yr to indicate an energy-efficient outcome for this context.”

3) Percentile-based limit
p(lighting_W, 0.95) <= 1500

“Cap the 95th percentile of whole-building lighting power at 1.5 kW to catch spikes.”

Why CEL again?

In short, CEL keeps the surface small while the leverage stays high. The expressions are readable to the domain expert who actually knows what "good" looks like, and the runtime is deliberately boring: no side effects, no imports, no file access. Because the rules live as data, every run can record exactly which rules were applied and what they computed. That makes audits and re-runs pleasantly unremarkable. And when a workflow crosses domains, the same ruleset shape still works; only the helper functions change per step. That combination ( small, safe, versioned, and composable ) is exactly what I want for SimpleValidations.

Having said that, I'm also building a GUI that allows the author to construct these expressions without needing to know the syntax. But for the power user, they can just drop in a yaml or json file with everything defined.

Go Yonder and Follow the Rules

Curious about wiring a CEL-based step into your workflow? Reach out — I'd love to discuss how you might leverage CEL for your data validation needs. That will help me tremendously as I continue to build out SimpleValidations.