Why Bun is Leaving Zig: The Full Story of the Rust Rewrite

Bun, the hyper-fast JavaScript runtime known for its incredible speed and Zig-based architecture, is being completely rewritten in Rust.
For a project that has over 22 million monthly downloads and earned first-party support on platforms like Vercel and Railway, changing the foundational language is a monumental risk. In software engineering, "everything all at once" rewrites are notoriously known as the fastest way to kill a project.
So why did Bun decided to do it anyway? It all comes down to a battle between development velocity and system stability.
The Trap of Mixed Memory Management
Bun started its life as a line-for-line port of esbuild from Go to Zig. At the time, Zig was a perfect match. It offered low-level control, unmatched performance, and clear syntax. In just one year of relentless solo coding, Jarred managed to ship an incredibly ambitious scope: a transpiler, a package manager, a test runner, and full Node.js compatibility.
But as Bun grew, stability became an elusive target.
JavaScript is a garbage-collected (GC) language. Modern engines like Safari’s JavaScriptCore (which powers Bun) operate on strict, complex rules for handling memory and exception tracking. Zig, on the other hand, leaves memory management entirely up to the developer, utilizing explicit defer and errdefer blocks to clean up resources.
When you mix a GC-managed stack with manually-managed system memory, edge cases explode. The team found themselves caught in a perpetual loop of tracking down critical, complex stability bugs, such as:
Use-after-free crashes in
node:zlibcaused by async operations interrupting thread pools.Memory leaks in
tlsSocketandfs.watch()due to reference count underflows.Heap out-of-bounds writes triggered by sneaky JavaScript callbacks firing mid-iteration.
Despite running aggressive fuzzing routines, 24/7 testing via Fuzzilli, and baking Address Sanitizer (ASAN) directly into their custom Zig compiler, the bugs kept coming.
Why Rust Swings the Needle
To solve this systematically, Bun needed a type system capable of enforcing strict resource ownership and automatic cleanup at compile-time.
While the team considered sticking to Zig and building custom "smart pointers," the developer ergonomics would have been incredibly messy. C++ was also evaluated, but it still relied heavily on human code reviews and style guides to prevent memory corruption.
Rust, however, solves the exact class of bugs Bun was fighting via its built-in mechanics
By moving to Rust, the vast majority of use-after-free, double-free, and error-path memory leaks simply become compiler errors.
The 11-Day Autonomous Rewrite
Manually rewriting over 535,000 lines of complex system code would normally take a team of engineers a full year—forcing a complete freeze on new features and bug fixes. To bypass this, Jarred executed an unconventional strategy: leveraging advanced AI models to transpile the codebase dynamically.
Following Anthropic's acquisition of Bun, Jarred used a pre-release version of Claude Fable 5 to orchestrate the migration. Instead of throwing a single prompt at the model, the migration was handled via roughly 50 dynamic, looping workflows over 11 intense days:
The Architecture Rules: They generated a comprehensive
PORTING.mdguide and data structure lifetime map to align Zig concepts with native Rust patterns.Mechanical Translation: Claude ported individual
.zigfiles to.rsfiles side-by-side, maintaining Bun's highly optimized, original architecture.The Compiler Loop: Autonomous loops attempted to compile the Rust crates, feed error logs back into the model, and iteratively patch the code until it compiled cleanly.
Adversarial Review: To trust over a million lines of AI-generated code, they utilized a split-context window setup. One AI instance authored the code, while an entirely independent "adversarial" instance aggressively searched for regressions, logic flaws, and hidden bugs.
Because Bun’s massive end-to-end test suite is written natively in TypeScript, the tests didn't care what language the underlying runtime was using. Within days of continuous iteration, the test suite went from failing to green light.
What Happens Next?
The initial Rust rewrite isn't designed to look like standard, idiomatic Rust. To maintain identical performance characteristics and minimize variables, it acts as a direct, structurally identical mirror of the original Zig code (even utilizing unsafe Rust blocks where strict pointers match the old architecture).
Now that the foundational architecture is stable and passing the test suite, the team is incrementally refactoring the codebase to eliminate unsafe blocks, adopt idiomatic Rust patterns, and prepare for the release of Bun v1.4.
For developers using Bun today, the change will be invisible in terms of APIs—but the runtime is about to become radically more resilient.
Smaller binary size
The initial changes in the Rust rewrite reduced binary size by 3.8 MB on Windows, 5.5 MB on macOS, and 6.8 MB on Linux. This is largely because we used too much comptime in our Zig code.
Bun v1.3.14 was the last version of Bun written in Zig. Bun v1.4.0 will be the first version of Bun written in Rust. It's available in canary now
bun upgrade --canary
Claude Code v2.1.181 (released June 17th) and later use the Rust port of Bun. Startup got 10% faster on Linux but otherwise, barely anyone noticed. Boring is good.
We are now building things at lightning speed :)
Enthino vendi thilakkunna Sambar...!



