How AI Rewrote Bun in Rust: 1 M+ Lines, 11 Days, 64 Parallel Claude Instances

The article details a full‑scale, AI‑driven rewrite of the Bun runtime from Zig to Rust, performed by a single engineer with 64 parallel Claude agents over 11 days, producing over a million lines of Rust code, cutting memory usage, binary size, and improving performance while documenting costs, bugs, and safety reviews.

TonyBai
TonyBai
TonyBai
How AI Rewrote Bun in Rust: 1 M+ Lines, 11 Days, 64 Parallel Claude Instances

Two months ago Bun announced a migration from Zig to Rust, sparking debate. Founder Jarred Sumner later posted a detailed account showing that a single person, aided by 64 parallel Claude instances, rewrote 535 k lines of Zig code into more than 1 M lines of Rust in 11 days, while Bun continued serving 22 M monthly downloads.

Background and Motivation

Originally created in 2021, Bun was written in Zig by Sumner and bundled a JavaScript/TypeScript/CSS transpiler, npm‑compatible package manager, Jest‑like test runner, Node.js compatibility layer, and HTTP/WebSocket client. Zig’s minimalism and performance enabled rapid development before the LLM era, but its lack of automatic memory management caused numerous bugs such as use‑after‑free, double free, memory leaks, and TLS session cache leaks. The team mitigated these with ASAN, fuzzing, and extensive testing, yet these were post‑mortem fixes rather than root‑cause solutions.

Why Rust Instead of C++

Although about 20 % of Bun already depends on C/C++ libraries, moving to C++ would only replace extern "C" glue code and still suffer from manual‑memory errors that require style guides and code reviews. Rust’s safety guarantees turn most of those bugs into compile‑time errors and provide automatic Drop ‑based cleanup, offering a more reliable feedback mechanism.

Engineering Approach

The team chose a full rewrite over incremental migration to avoid transitional code that would linger for months. The initial strategy was a “faithful mechanical translation” that kept the new Rust code structurally close to the original Zig, postponing unsafe‑reduction and idiomatic Rust refactoring to after the v1.4 release.

A core mechanism was the separation of "implementer" and "adversarial reviewer" roles. One Claude acted as the implementer while at least two other Claudes served as reviewers who only saw diffs, were told the code was wrong by default, and tried to find defects. This 1 implementer + 2 reviewers model caught many subtle bugs.

Async‑close dangling pointer: replaced Box with Box::leak to avoid premature free.

Negative timestamp nsec overflow: switched from trunc() to floor().

Immediate‑evaluation trap of unwrap_or: changed to lazy unwrap_or_else.

Workflow

Preparation involved a three‑hour discussion with Claude to map Zig patterns to Rust, producing a PORTING.md document. Claude then generated a LIFETIMES.tsv file with lifetime annotations, which also underwent adversarial review.

A trial run on three .zig files validated the process before scaling to all 1 448 files.

Early pitfalls included multiple Claude instances racing on git stash and git reset --hard, corrupting each other’s work. The team enforced rules prohibiting non‑file‑specific git commands and disallowing slow commands like cargo. Work was split into four independent worktrees, each running 16 Claude instances, peaking at 64 concurrent agents.

Claude wrote roughly 1 300 lines per minute; each line passed through two independent reviewers and a fix round before being committed.

Compilation exposed about 16 k errors, mainly from crate dependency cycles after splitting the codebase into ~100 crates. Each crate was handled by a small loop of one implementer, two reviewers, and an integrator.

Testing convergence was dramatic: the CI suite started with 972 failing tests, dropped to 23 after two days, and finally all six platforms (Linux x64/arm64, macOS x64/arm64, Windows x64/arm64) turned green, allowing the PR to merge into the main branch.

Results

Duration: 11 days (May 3 – May 14), 6 778 commits.

Net code change: +1 009 272 lines.

Test suite executed >3.7 million expect() assertions with zero skips or deletions.

Token usage: 5.9 billion input tokens, 0.69 billion output tokens, 720 billion cache‑read operations; cost ≈ $165 000.

Estimated human effort: three engineers for roughly one year, during which all Node.js compatibility work, bug fixes, security patches, and new features would have been frozen.

Improvements

Memory: Bun.build() leak dropped from ~3 MB per build (6.7 GB after 2 000 builds) to a stable ~609 MB after 2 000 builds.

Binary size: initial Rust build reduced binary size by 3.8 MB (Windows), 5.5 MB (macOS), and 6.8 MB (Linux). After linker deduplication and ICU resource trimming, overall size shrank ~20 % (Windows 94 MB → 76 MB, Linux 88 MB → 70 MB).

Stack reuse: LLVM IR generated by the Rust compiler inserts lifetime end markers, allowing stack slot reuse that previously required manual function splitting in Zig.

Performance: on an EC2 Xeon Platinum 8488C, HTTP throughput increased 2.8‑4.8 % (Bun.serve from 169.6 k req/s to 177.7 k req/s). Typical workloads (next build, vite build, tsc ‑b) saw 2.2‑4.7 % faster execution.

Production validation: Prisma Compute’s beta runs on the Rust version, fixing memory‑leak and connection‑pool recovery issues. Claude Code cold‑start time improved ~10 % (517 ms → 464 ms).

Known Regressions

Nineteen issues were discovered and fixed; notable examples include: debug_assert! macro removal in release builds causing side‑effect loss.

Odd‑length slice panic when using bytemuck::cast_slice on UTF‑16 data.

Boundary‑check differences between Zig’s ReleaseFast (no checks) and Rust’s default release (checks retained) exposing a buffer overflow.

Differences in compile‑time formatting: Zig’s comptime handling versus Rust’s runtime formatting leading to malformed string handling.

Ongoing Safety Review

After merging to main, the team ran 11 rounds of Claude Code Security reviews, addressing each finding. Continuous 24/7 fuzzing of all parsers (JavaScript, TypeScript, CSS, JSON5, YAML, TOML, etc.) has executed over 1 000 billion inputs, generating ~15 PRs.

Approximately 4 % of the Rust code still contains unsafe blocks (about 1.3 k occurrences in 78 k lines), mostly thin wrappers around C/C++ libraries. The proportion is expected to shrink as the codebase moves from a faithful Zig port to idiomatic Rust.

Conclusion

The experiment demonstrates that AI agents can drive a large‑scale language rewrite when paired with disciplined engineering practices: a full‑rewrite strategy, an initial mechanical translation, adversarial reviewer separation, treating compile errors as a massively parallel task queue, and a strict zero‑test‑skip policy. The effort cost $165 k, took 11 days, and deleted no tests, providing a concrete reference point for future AI‑assisted rewrites of critical infrastructure.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PerformanceAI code generationRustBunmemory safetyClaudecode rewriting
TonyBai
Written by

TonyBai

Tony Bai's tech world (tonybai.com). Not satisfied with just "knowing how", we strive for mastery. Focused on Go language internals, high-quality engineering practices, and cloud‑native architecture, exploring cutting‑edge intersections of Go and AI. Gophers who pursue technology are welcome—follow me and evolve with Go.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.