How It Compares
datalogic-rs is a JSONLogic engine: rules are JSON data, evaluated by one Rust core that ships as eight packages (Rust, Node.js, browser WASM, Python, Go, JVM, .NET and PHP). This page compares it with the alternatives people most often weigh it against. For raw numbers and methodology, see Performance and the benchmark matrix.
| Dimension | datalogic-rs | json-logic-js | json-logic-engine | jsonlogic-rs | GoRules ZEN | CEL |
|---|---|---|---|---|---|---|
| Format | JSONLogic (JSON data) | JSONLogic (defines the standard) | JSONLogic superset | JSONLogic | Proprietary JDM + Zen expression language | CEL expression grammar (not JSON) |
| Languages | One core, official bindings for Rust, Node, WASM, Python, Go, Java, .NET, PHP | JS core; other languages are separate community ports | JS/TS only | Rust (single crate, Python/WASM wrappers exist but stale) | Rust core with several bindings | Go/Java mature, others varying |
| Standard compliance | Passes the official JSONLogic test suite, plus opt-in extensions | The reference implementation | Superset with minor deviations | Passes core suite | Not JSONLogic | Own spec |
| Sandboxing | No eval, no I/O, core forbids unsafe code | No eval | No eval | No eval | Function nodes execute JavaScript (QuickJS) | Non-Turing-complete, strong formal story |
| Tooling | React visual editor, step-through trace debugger, online playground, rule checker (check) | Play page | None official | None official | JDM editor + commercial BRMS | Community playgrounds |
| Extensibility | Custom operators per host language | Custom ops in JS | Custom ops (incl. async) in JS | Limited | Custom nodes | Extension functions per environment |
jsonlogic-rs on crates.io is
bestowinc/json-logic-rs, a
different project despite the near-identical name. This crate is
datalogic-rs. The section below compares the
two.
One engine vs. N ports
JSONLogic promises portability: rules are plain JSON, so any language can evaluate them. In practice json-logic-js is the JavaScript reference, and each other language relies on an independent reimplementation: community ports for Python, PHP, Go, Ruby, Java and more, each with its own maintainer, release cadence and bugs. The ports drift. Truthiness edge cases, type coercion, null handling and error behavior diverge one patch release at a time, and a rule that passes tests in your Node service can evaluate differently in your Python batch job.
datalogic-rs compiles one Rust core into every runtime. The Node addon, the WASM package, the Python wheel, and the Go, Java, .NET and PHP bindings all embed the same engine, and none of them reimplements an operator. Two checks keep the languages in step:
- The same 2,128-case conformance battery (66 suites) runs against the core
in CI, and again through the Node, WASM, Python and Go bindings and the
C ABI that the JVM, .NET and PHP bindings load. A shared scenario suite
(
bindings/scenarios/api.json) checks the API surface in all eight. - The flagd
fractionaloperator is byte-compatible with the canonical Go evaluator’s MurmurHash3 bucketing, so a hash-based percentage rollout puts the same user in the same bucket in every language.
When to choose which
datalogic-rs fits when your rules should be data: stored in a database column, diffed in review, generated by a UI, and evaluated with identical semantics on the client and every backend service. What sets it apart is one engine shared across eight runtimes and an official visual debugger for the standard. Each alternative below is the better pick for the case it describes.
json-logic-js
The reference implementation, and the project that defines the JSONLogic standard. datalogic-rs passes the same official test suite, so existing json-logic-js rules run unchanged.
Choose it when: you only need JavaScript, you want the smallest and longest-used dependency, and the reference engine’s speed is enough at your rule volume. As the standard’s source of truth, it is the default choice for a JS-only stack.
Choose datalogic-rs when: the same rules must also run outside JavaScript, evaluation is hot enough to show up in profiles (the native engine measures about 84x faster across the shared benchmark suites), or you want the visual debugger and playground.
Migrating is close to a package swap; the full mapping is in Coming from json-logic-js.
json-logic-engine
A fast, actively maintained JavaScript engine: its compiled mode is the only non-Rust subject within the same order of magnitude as datalogic-rs in the benchmark matrix.
Choose it when: your stack is JS/TS end to end and you want JS-native ergonomics, above all async custom operators, which datalogic-rs’s synchronous custom-operator callbacks do not offer.
Choose datalogic-rs when: you need one core across many languages, native (non-JS) bindings, closer adherence to the reference semantics, or the visual tooling. Rules that stay inside the shared JSONLogic standard carry over unchanged.
jsonlogic-rs (bestowinc)
The similarly named crate on crates.io, and the comparison people search
for most. jsonlogic-rs is a single-crate Rust implementation of core
JSONLogic with an apply(&Value, &Value) API: there is no compile step, so
every call re-walks the rule JSON. Python and WASM wrappers exist in the
same repository but have not seen recent releases. It is a small
dependency for occasional evaluation of standard rules.
Choose it when: you want a minimal one-function crate, your rules stick to the core standard, and evaluations are infrequent enough that per-call rule walking does not matter.
Choose datalogic-rs when: evaluation is hot (compile-once evaluation
measures about 28x faster geomean on the shared suites), you need the
extended operators (datetime, string, try/throw, flagd), custom
operators, tracing, or any of the non-Rust bindings. Both engines speak
JSONLogic, so rules carry over unchanged; switching is confined to the Rust
call sites, and the quick start shows the
equivalent one-liner.
GoRules ZEN
A business-rules platform built around decision tables and graphs (a proprietary JDM format), with a commercial editor. It solves a bigger problem than expression evaluation.
Choose it when: you want a full BRMS abstraction for business users: decision tables, graph orchestration, and a polished commercial editing experience on top of the engine.
Choose datalogic-rs when: you want a lighter embedding around an open standard, or a stricter sandbox: ZEN’s function nodes run JavaScript (QuickJS), while datalogic-rs runs no code a rule supplies.
CEL
Common Expression Language is the standard safe expression language in the Kubernetes and Envoy ecosystems, with a non-Turing-complete guarantee and a formal spec.
Choose it when: you want an expression grammar (not JSON) and its ecosystem integrations, or you already live in a CEL-native environment such as Kubernetes admission control.
Choose datalogic-rs when: rules should be plain JSON: storable, diffable, and UI-generatable with no grammar or parser to maintain, plus an official visual editor for the people who write the rules.
The numbers
Geomean execution time across 51 benchmark suites (Apple M2 Pro; median of 3 samples; ratios are pairwise shared-suite geomeans; methodology in the benchmark matrix).
datalogic-rs (native Rust) | 10.3 ns (■) 1x
json-logic-engine (JS, compiled) | 63.3 ns (■■■■■■) 7.0x
json-logic-engine (JS, interpreted) | 234.8 ns (■■■■■■■■■■■■■■■■■■■■■■■) 25.8x
jsonlogic-rs (bestowinc Rust engine) | 264.2 ns (■■■■■■■■■■■■■■■■■■■■■■■■■■) 28.1x
json-logic-js (Reference JS library) | 465.1 ns (■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■) 83.6x
The WASM build under Node measures 900.5 ns (88x native), so on Node servers use the native binding; the WASM package is for browsers and edge runtimes.
Proof: the same rule everywhere
One rule, one datum, eight runtimes:
{
"and": [
{">=": [{"var": "age"}, 18]},
{"==": [{"var": "status"}, "active"]}
]
}
With data {"age": 25, "status": "active"}, every binding returns true:
| Runtime | One-line call |
|---|---|
| Rust | datalogic_rs::eval_str(rule, data)? |
| Node.js | apply(rule, data) |
| Browser (WASM) | new Engine().evalStr(rule, data) |
| Python | apply(rule, data) |
| Go | datalogic.Apply(rule, data) |
| Java | engine.apply(rule, data) |
| C# | engine.Apply(rule, data) |
| PHP | $engine->apply($rule, $data) |
All eight calls run the same compiled core. Try the rule live in the playground (live Studio), then pick your language in Installation.
See Also
- Performance & Benchmarks — methodology, input projection, and optimization tips
- Coming from json-logic-js — migrating from the JavaScript reference implementation
- Operators Overview — all 84 built-in operators across 10 families
- Sandboxing Untrusted Rules — safety guarantees and resource bounds