Platform · Calculations
SPEC 05Same inputs, same outputs. Every time, including last March.
Derived values are only worth keeping if you can say how they were made. Calculations in OrdinateDB are deterministic by construction, replayable over corrected history, and every result carries the provenance of the data that produced it.
Expressions, then plugins
SPEC 05 §2An expression language for the 95% case. WASM for the rest.
Most plant calculations are arithmetic over a handful of series with time alignment done correctly — specific energy, yield, OEE components, totalised flows. The expression language covers these in a line or two, with units checked against the registry at definition time, not discovered at 2 a.m.
For the remainder — a vendor’s compressor model, a first-principles heat balance — you compile a plugin to WASM from any language that targets it. Plugins run sandboxed under the same determinism contract as expressions: no clock, no network, no filesystem. Inputs in, outputs out.
expr: motor_power_kw / flow_m3_h align: 1m mean, gaps excluded units: kW / (m³/h) → kWh/m³ ✓ checked
the worst pct_good of the inputs flows into the result. derived numbers confess too.
Deterministic by construction
SPEC 05 §1 · §4A calculation is a pure function of its declared inputs. That is enforced, not encouraged.
Expressions cannot reach the wall clock, random numbers or anything outside their declared input series; the WASM sandbox denies plugins the same things. So replaying a calculation over the same archive slice produces byte-identical results — which is what makes recalculation over corrected history safe, and what makes “where did this number come from?” a question with an answer.
Calculations run on a schedule, on an event (a point arriving, an episode closing), or both. Either way the trigger is recorded alongside the result.
Recalculation over corrected history
SPEC 05 §5 · SPEC 03 §7Late data happens. Bitemporal storage means it does not lie.
A lab result lands two days after the batch. A drained backlog fills yesterday’s gap. When corrected history arrives, every dependent calculation re-runs over the affected window — automatically, in dependency order — and because storage is bitemporal, both readings survive: the value as it was known at the time, and the value as it is known now. The month-end report you issued on the 1st is still reproducible on the 30th.
ask for the value as-of any knowledge time. neither answer overwrites the other.
The expression language, the plugin ABI and the replay semantics are all in the spec — read them before you trust us.