NodeFox logoNodeFox
Back to Blog
engineering
rust
performance

Why We Chose Rust for Our Core Engine

E

Engineering Team

3 min read

Why We Chose Rust for Our Core Engine

When we started building NodeFox, we had a choice every orchestration startup faces: build the execution engine in a dynamic language for speed of development, or invest in a systems language for speed of execution.

We chose Rust. Here's why — and what we learned.

The Problem We Were Solving

Workflow orchestration engines process thousands of nodes per second. Each node involves JSON parsing, schema validation, expression evaluation, and state management. In Python or Node.js, these operations add up fast — especially when running in a browser.

We needed an engine that could:

  1. Run in the browser via WebAssembly
  2. Parse and validate JSON at near-native speed
  3. Manage complex directed-graph state without garbage collection pauses
  4. Stay deterministic — same input, same output, same performance

Why Not JavaScript?

We prototyped in TypeScript first. The engine worked, but performance was unpredictable. V8's JIT compilation meant that the same workflow could take 50ms or 200ms depending on optimization heuristics. For an orchestration engine where users expect consistent sub-100ms execution, this variance was unacceptable.

Why Not Go?

Go's goroutine model is excellent for server-side orchestration, but Go's WebAssembly output is large (often 10MB+) and doesn't integrate well with browser APIs. We needed something that compiled to lean, fast WASM.

Why Rust

Rust gave us three things no other language could:

  • Predictable performance: No garbage collector, no JIT warmup, no runtime surprises. The same workflow takes the same time, every time.
  • Small WASM binaries: Our entire engine compiles to under 2MB of WebAssembly. That's smaller than most JavaScript bundles.
  • Memory safety without GC: Rust's ownership model eliminates data races and memory leaks at compile time. In an engine processing user-defined workflows, this safety is non-negotiable.

The Learning Curve

We won't pretend it was easy. Rust's borrow checker is demanding, and the team spent the first month fighting it more than writing features. But once we internalized the ownership model, our bug rate dropped dramatically. Entire categories of bugs — null pointer dereferences, data races, use-after-free — simply couldn't happen.

Results

After six months with the Rust engine in production:

  • Execution time: 3-5x faster than our TypeScript prototype
  • Memory usage: 60% lower peak memory
  • WASM bundle size: 1.8MB (vs 12MB with Go, ~4MB with optimized TS)
  • Production bugs in the engine: Zero memory-related issues

Was It Worth It?

Absolutely. The upfront investment in Rust paid for itself in reliability and user experience. When a user drags a node onto the canvas and connects it, the execution preview updates instantly. That responsiveness is only possible because the engine processes the entire graph state in under 10ms.

If you're building something that needs to be fast, safe, and run everywhere — the browser, the server, the edge — Rust with WebAssembly is hard to beat.