Bun's Zig-to-Rust rewrite ships its first canary

Bun 1.3.14 was the last release built on the original Zig codebase. Bun 1.4's canary is the first built substantially in Rust, the product of an 11-day, roughly 535,000-line agent-driven rewrite. Early numbers from creator Jarred Sumner claim 128 bugs fixed relative to 1.3.14 alongside real memory-usage improvements.

Younes Bekrar8 min read
ShareXLinkedInFacebook
Bun's Zig-to-Rust rewrite ships its first canary, and early bug-fix numbers look real

Bun 1.3.14 is the last release on the original Zig codebase. The first Bun 1.4 canary is the first build shipped substantially rewritten in Rust. Creator Jarred Sumner says the move covered roughly 535,000 lines in about 11 days, with Claude Fable 5 acting as the primary coding agent rather than autocomplete with a marketing budget. Anthropic bought Bun's parent company in December 2025, which put the runtime's engineers inside the same firm as the model doing most of the translation, a proximity most production language runtimes do not get when they talk about "AI-assisted" rewrites. I opened the canary notes looking for a vibes announcement. The bug-fix count is what made me keep reading.

Zig was a speed bet. The crashes piled up at JSC

Bun picked Zig partly for fine-grained memory layout without C's preprocessor mess, which fit a runtime chasing Node and Deno on startup and execution speed. Sumner's stated reason for leaving is the bug class that manual memory management accumulates at Bun's size: use-after-free, double-free, and lifetime mistakes around the JavaScriptCore embedding. The ugly crashes tended to live where Bun's own allocators meet JSC's garbage collector and the two sides disagree about how long an object lives.

Rust's ownership rules exist to catch that category at compile time. The pitch for the rewrite is not "Zig bad." It's that a manually managed host wrapped around a GC'd engine is exactly where borrow checking earns rent, instead of hoping review and fuzzing catch every mismatched lifetime.

Anyone who has chased a heisenbug at a GC boundary knows the genre. Reproduces under load, vanishes under ASAN timing, comes back in a customer's CI. Zig didn't invent those bugs. Bun's growth and JSC embedding just kept paying the tax. Sumner's public framing treats Rust as a way to make a class of those mistakes fail closed at build time.

Performance was the original Zig argument, and Sumner has not claimed the Rust canary is a wholesale speed win across every microbench. The early story he's telling is correctness and memory behavior first. Speed comparisons will get louder if 1.4 stabilizes without giving back the runtime's reason to exist.

Use-after-free and double-free bugs are especially punishing in a runtime people adopt for speed, because the failure mode looks like "Bun crashed again" rather than "my app has a logic error." Shifting that class left into the compiler is a product decision as much as an engineering taste.

Eleven days, with humans on the scary boundaries

Sumner's account treats Fable 5 as the main author of the translated code, walking the Zig tree file by file and subsystem by subsystem into idiomatic Rust. Humans reviewed diffs, kept the existing test suite running, and intervened at the places a naive translation could compile while changing behavior: the JSC embedding, custom allocators, native module bindings.

The Anthropic acquisition matters to the timeline. Bun's team had tighter access to the model and, presumably, to people building agentic coding workflows inside Anthropic, not the arm's-length API relationship everyone else gets. Sumner has framed the 11-day clock as realistic because of that access, not as a claim that any shop with a Claude key could shove 535,000 lines through over a long weekend.

Eleven days is still a wild number next to half a million lines, even with that caveat. The believable version, and the one Sumner keeps pointing at, is agent-speed translation plus humans glued to the boundaries that can silently change semantics. The unbelievable version is "press button, receive runtime." The canary exists because they are still in the middle of finding out which subsystems got the first version.

I care less about whether Fable 5 wrote seventy or ninety percent of the lines than about whether the test suite and outside workloads keep agreeing with 1.3.14's behavior. Authorship percentages make good podcast bait. Behavioral drift on native modules makes angry issues.

The human review load is the hidden cost in Sumner's eleven-day clock. Agents can emit Rust at a terrifying rate. Someone still has to stare at the JSC boundary until they trust it. That staring does not show up in the line-count headline, and it is probably where the timeline would break for a team without Bun's new corporate proximity to the model.

1.3.14 frozen, 1.4 canary live

1.3.14 is the deliberate last Zig-only line in the sand, so anyone bisecting a regression against the old architecture has a clean last-known-good. 1.4.0 canary is where the Rust paths are actually running. It's still canary because a rewrite this wide will invent new bugs while closing old ones, and the team wants outside workloads before it becomes the default install.

Sumner says the canary already fixes 128 bugs relative to 1.3.14, tracker issues that reproduced on Zig and don't on Rust, plus memory improvements he ties to ownership rules removing leak and double-allocation patterns from parts of the old code. Those are his numbers, not an audit. Early canary users have mostly echoed the memory direction on long-running server workloads, lower peak RSS versus matched 1.3.14 runs, without enough sample size to treat the exact figures as settled.

Freezing 1.3.14 as the Zig endpoint is a gift to anyone who has to explain a production pin to a manager. You can stay on the last Zig build on purpose while you bruise the canary elsewhere. Lots of rewrites blur that line and force people to guess which commit was "still the old world."

I'll treat the 128 figure as a directional claim until the tracker labels are easy for outsiders to tally. The memory anecdotes are easier to believe in outline, Rust making certain leak patterns harder, even before the RSS deltas get a proper bake-off.

Canary users running long-lived servers are the right early audience. CLI one-shot scripts will not stress the allocator paths that made Zig painful. If you only try `bun --version` and a toy script, you will learn almost nothing about whether 1.4's memory story holds.

Stay on 1.3.14 in prod. Bruise the canary elsewhere

Production stays on 1.3.14 or whichever last stable Zig build you trust until 1.4 leaves canary. Point the canary at staging or a sacrificial service and file what breaks, Bun is asking for that traffic. Native modules and anything on FFI or native bindings deserve the meanest tests. Those were the high-risk translation zones and the likeliest place for quiet behavioral drift.

Whether an 11-day, half-million-line rewrite is a precedent or a one-off inside Anthropic's walls is Sumner's own framing leaning toward the latter. I'll leave it there until someone outside that orbit ships something comparable and survives a stable cycle without swapping one bug class for another.

My own plan matches the boring advice: keep prod on 1.3.14, run the canary where a crash is a Slack message instead of a pager, and watch native addons first. If the 128 closed issues stay closed and the new ones stay rare, 1.4 earns a wider install. If not, the Zig line in the sand is still there on purpose.

For now the story is concrete enough without inflating it: Sumner, 535k lines, 11 days, Claude Fable 5, 128 bugs closed versus 1.3.14, memory anecdotes from early canary users, Anthropic's December 2025 acquisition in the background. That package is already strange. It does not need a sermon about what every runtime will do next year.

  • Open Source

Keep reading