The live logic runtime.
Swap a function in a running production process — in ~500 microseconds.
Provably safe. Canaried against live traffic. Instantly reversible. An embeddable JIT scripting runtime — for humans, and for AI agents.
“LaunchDarkly flips booleans. Blaze swaps functions — in 500 microseconds, with a proof, a canary, and an undo button. And it is how you let an AI touch production logic without fear.”
$ git clone https://github.com/grloper/Blaze && cd Blaze && cargo run -p blaze-jit --release --example living_service -- --script
See it run
A living service under fire.
An HTTP risk-scoring service whose logic is a .blaze program, hot-swapped while thousands of requests per second pour through it. Six live edits — every beat asserted, over real HTTP, under load.
Recorded deterministically from docs/living_service.tape. Hammered from four threads by tests/living_service.rs.
How it can be safe
The firewall: callers read the signature, not the body.
Blaze is an incremental compiler first. Source is a fine-grained salsa query graph in which a function’s lowered IR depends on its own text and its callees’ signatures — never their bodies. That asymmetry makes every edit’s blast radius a computed fact, not a guess.
An edit to a function’s body re-lowers only that function — every caller is a byte-for-byte memo hit. An edit to its signature forces exactly the callers that read it into the radius. The graph computes the blast radius as a byproduct of recompiling the edit.
A defect is proven — nothing goes live
Syntax error, undefined callee, arity or type mismatch, undefined variable. Nothing is compiled or patched; the previous known-good generation keeps serving every call untouched.
The edit changed nothing that matters
No function’s IR changed — a comment, whitespace. Zero codegen, zero generations, and it costs nothing at all.
A body changed, signatures held
One lock-free atomic pointer store — valid under concurrent execution, because the firewall guarantees no caller’s code mentions anything about the callee but its slot.
A signature moved (or a function was removed)
The graph forces every caller in the radius. The whole proven set recompiles and commits under a quiescence barrier — mismatched caller/callee ABIs are never observable.
The category
Everything else guesses, flips, or restarts.
Live behavior change isn’t new — but every existing approach trades away granularity, proof, or speed. Blaze keeps all three.
| Approach | Unit of change | Where it runs | Reload speed | Proven radius | Per-rule canary | Rollback |
|---|---|---|---|---|---|---|
| LaunchDarkly | Boolean / config flags | SaaS eval ($20k+/yr) | flag flip | n/a (no code) | ✗ | flag off |
| OPA / Rego | Whole policy bundle | In-process | whole-bundle reload | ✗ | ✗ | redeploy bundle |
| Sandbox / microVM | Whole script / process | Out-of-process | seconds (spin-up) | ✗ | ✗ | restart |
| dlopen / hot-patch | Native library | In-process | ms, guessed diff | ✗ guessed | ✗ | reload library |
| Blaze | Individual functions | In-process JIT | ~500µs, proven | ✓ per edit | ✓ live traffic | ✓ one call |
For AI agents
Let an AI touch production logic — without fear.
The same pipeline that protects a human protects an autonomous editor. Every proposed edit runs a gauntlet before it can reach a real request.
The killer scenario: an edit that passes every offline test.
A candidate clears the whole offline eval set — then loops forever on an input shape the eval set never covered. The canary shadow-executes it on a sampled slice of live traffic, under the primary’s own fuel budget, and traps FuelExhausted. It auto-aborts and is never promoted. The caller only ever saw the live answer.
“The blast radius of a bad idea is a shadow execution, not an outage.”
Benchmarks
Real numbers, honestly labeled.
cargo run you can reproduce.Reload latency, per edit class
bench_reload — a 40-function call chain where every function transitively depends on the edited leaf; median of repeated edits.
| Event | Latency |
|---|---|
| Full cold compile (≈ a restart’s compile cost) | 8.5 ms |
| Body edit → SafeSwap (radius 1 of 40) | 0.74 ms |
| Comment → NoEffect (radius 0) | 0.54 ms |
| ABI edit → Relink (radius 2) | 1.9 ms |
$ cargo run -p blaze-jit --release --example bench_reload
Call throughput
bench_calls / bench_vs_interpreter — a trivial leaf (dispatch cost), and the same branchy risk rule vs. an embedded interpreter (rhai), cross-checked to agree on every input.
| Path | Throughput |
|---|---|
call(name) — lock + string lookup per call | ~19 M calls/s/thread |
call_handle — resolve once, then lock-free | ~50 M calls/s/thread |
call_handle, 4 threads (~94% linear) | ~188 M calls/s |
rhai call_fn — AST interpreter, same rule | ~0.96 M calls/s/thread |
~51× the interpreter on identical logic — and still hot-swappable, which a compiled dylib is not. That is the “swap functions, don’t flip booleans” number.
$ cargo run -p blaze-jit --release --example bench_vs_interpreter
Canary overhead on the live path
bench_canary — what call_canary costs the live path, on a ~46 ns leaf so the deltas are visible. The caller always gets the live answer.
| Mode | Overhead |
|---|---|
| Idle (no candidate — one atomic load) | +~4 ns/call |
| Shadowing 1% of calls (lock-free sampler) | +~4 ns/call |
| Shadowing 100% of calls (a full shadow every call) | +~220 ns/call |
$ cargo run -p blaze-jit --release --example bench_canary
Claims → proofs
Every claim is a theorem with a test.
Every “instant”, “safe”, and “proven” on this page traces to a named test that attacks the guarantee from a second thread while it holds. Here are the strongest — each links to its function on GitHub.
FuelExhausted, never hangs — the runtime is healthy afterward.
live.rs::infinite_loop_aborts_with_fuel_exhausted
FuncHandle path is torn-free under concurrent hot-swaps.
live.rs::handle_calls_are_correct_under_concurrent_body_swap
rollback(gen) reverts through the same swap protocol, torn-free under a second thread.
journal.rs::rollback_is_sound_under_concurrent_execution
x / 0 cannot fault the host — division is guarded in codegen.
jit.rs::division_is_guarded_and_cannot_fault_the_process
Honest limits
A focused core, not a general language.
What Blaze deliberately does not do yet — so you know before you build on it. None of these change the reload and safety guarantees.
One file, one flat namespace
A program is a single .blaze source of top-level functions. No modules, no imports.
Two scalar types only
int (i64) and float (f64). No strings, arrays, structs, or pointers — which is also why a script can’t corrupt the host: there are no memory operations to abuse.
State lives in the host
Blaze functions are pure over their scalar arguments; all persistent state is the embedder’s. That is exactly what makes state survive every reload.
Retired code is retained, not freed
A concurrent caller may still be inside an old generation mid-swap, so old code pages stay mapped. The cost grows with edit count × edited-function size.
A canary re-executes each sampled call
Mirror only logic free of observable host side effects (the norm for scoring functions). A canary is an evaluation mode, not steady state.
StateMigration is reserved
A reserved EditClass for when script-owned persistent state lands with layout versioning. Today it cannot occur.