Bun Completes 11-Day AI-Driven Code Migration from Zig to Rust

iconMetaEra
Share
AI summary iconSummary
In May 2026, Bun announced a project update, completing an 11-day AI-driven code migration from Zig to Rust. The effort involved over one million lines of code, 6,778 commits, and 64 parallel Claude instances, costing $165,000. Memory usage decreased from 6.7 GB to 609 MB after 2,000 builds, with performance improvements of 2–5%. The migrated code now includes 13,000 unsafe keywords and 19 regressions. Anthropic now owns the project. This AI and crypto update highlights a major shift in the project’s infrastructure.
The Bun project completed a major code migration from Zig to Rust in May 2026, involving over 1 million lines of code changes and 6,778 commits within 11 days. The migration was carried out in parallel using 64 Claude instances, incurring $165,000 in API costs. After the migration, memory leaks were fundamentally resolved: memory usage stabilized at 609 MB after 2,000 builds, down from 6.7 GB; performance improved by 2% to 5%, and binary size decreased by approximately 20%. However, the codebase contains approximately 13,000 unsafe keywords—178 times more than similar projects—and has 19 known regressions. The million-line code change could not be manually reviewed line by line. Bun has since been acquired by Anthropic.

Article author and source: InfoQ

In May 2026, the Bun project completed a large-scale code migration that was nearly unprecedented in the history of software development.

The migration launched on May 3 and was officially merged into the main branch on May 14, taking just 11 days. Writing the code took only 6 days, and the entire process was public. However, Jarred Sumner took nearly a month to write his blog post summarizing it—much longer than the time spent writing the code.

This JavaScript runtime originally consisted of 535,496 lines of Zig code, excluding comments, with approximately 20% written in C++ and incorporating multiple C/C++ libraries. It has now been rewritten in Rust using AI, involving over one million lines of code changes, 6,778 commits, and approximately 50 dynamic workflows executed in Claude Code.

According to data disclosed by Sumner, this rewrite consumed 5.9 billion uncached input tokens, 690 million output tokens, and 72 billion cached input token reads, costing approximately $165,000 at API pricing rates.

Sumner said this represents the cutting edge of what current technology can achieve. He estimated that if three engineers fully familiar with the Bun codebase were to manually complete this migration, it would take approximately one year—and during that time, the team would be nearly unable to continue developing new features, fixing bugs, or applying security patches.

After this rewrite, Bun v1.3.14 will be the last Zig version, and Bun v1.4.0 will be the first Rust version.

1. Result: Reduced from 6.7 GB memory leak to 609 MB stable

Bun began as a Zig project with an exceptionally broad scope: it serves as a JavaScript and TypeScript transpiler, bundler, package manager, test runner, module resolver, and HTTP and WebSocket client, while also implementing the Node.js API layer. This extensive feature set has led to over 22 million monthly CLI downloads and garnered support from projects and companies such as Vercel, Railway, DigitalOcean, Claude Code, and OpenCode.

But this same width has also presented some challenges for Bun.

In Bun v1.3.14, there was a long-standing issue: when calling Bun.build() repeatedly, memory would continuously accumulate without ever being released. Each build leaked approximately 3 MB—seemingly small, but if you're running a development server where each request triggers a build, memory would be slowly consumed until the process crashed.

In actual testing, memory usage was 1.9 GB after 500 builds, 3.5 GB after 1,000 builds, 5.1 GB after 1,500 builds, and surged to 6.7 GB after 2,000 builds.

This is just the tip of the iceberg among numerous memory issues. In the bug fix list for v1.3.14, Sumner listed a long series of issues:

When .reset() is called in the zlib module while an asynchronous .write() is still executing in the thread pool, the process crashes due to "use-after-free" on the heap; nested JavaScript callbacks in the http2 module trigger a hash table rehash, causing internal stream pointers to become invalid; during iteration in UDPSocket.sendMany(), if user code alters the socket's connection state via valueOf or toString callbacks, an out-of-bounds write occurs; when crypto.scrypt fails to allocate the output buffer, the callback and the protected password buffer are never released; ...

The commonality among these bugs is clear—they almost all point to the same root cause: mixing garbage collection with manual memory management within the same software.

Modern engines like JavaScriptCore (and V8) have extremely strict rules for exception handling and GC, while Zig, like C, does not automatically manage memory. When these two paradigms coexist within the same process, every memory allocation must be reviewed line by line: where are these bytes freed? How is it ensured that they are freed only once? Are JavaScript exceptions properly checked? Is this pointer managed by GC visible to the conservative stack scanner? Is this GC-managed memory or manually managed memory?

Even more concerning is that the team has not been idle. They have modified the Zig compiler to add Address Sanitizer (ASAN) support, run ASAN tests in CI with every commit, build with ReleaseSafe on Windows, perform 24/7 fuzzing with Fuzzilli, and conduct extensive end-to-end memory leak tests. Yet, crash reports continue to pour in.

“Our bug fix list is making us feel terrible; I’m tired of going to sleep worried about Bun crashing,” Sumner wrote. He does not blame Zig—other Zig users have not encountered issues like Bun’s, because combining GC with manual memory management is an extremely rare requirement, one that almost no language is designed to support.

The Rust version, on the other hand, maintains a stable memory usage of 609 MB when executing Bun.build() 2,000 times.

In addition to fundamentally resolving the memory leak issue, the Rust rewrite has brought improvements in several other areas.

In terms of stability, v1.4.0 fixed 128 reproducible bugs from v1.3.14, addressing issues ranging from memory leaks and crashes to incorrect color display in help text.

By volume, combining the Rust rewrite, ICU changes, and identical code folding, Bun has reduced its binary size by approximately 20% on Linux and Windows.

Performance has generally improved by 2% to 5%. Bun.serve increased from 169,600 req/s to 177,700 req/s, and node:http increased from 103,800 to 108,500. In real-world scenarios, next build decreased from 13.62 seconds to 13.03 seconds, and tsc batch compilation decreased from 0.94 seconds to 0.89 seconds.

After Claude Code was released based on Rust Bun, the startup time on Linux decreased from 517ms to 464ms, about 10% faster.

2 Method: 64 Claude instances, 11 days, 50 workflows

How Sumner did it may be the most noteworthy part—because his approach differs from the traditional method of "having AI write code."

Sumner broke the entire process into approximately 50 dynamic workflows, each of which is a loop. He described this pattern using pseudocode in his blog:

Each task has a context (such as a Jira ticket or GitHub issue), Claude writes code based on this context, then two reviewers (also Claude) review the code, and finally incorporates the feedback. Once completed, the next task is taken.

This pattern runs throughout the entire rewriting process. Each workflow is responsible for a specific goal:

  • Generate a porting guide mapping Zig's patterns and types to Rust's patterns and types;
  • Mechanically port each .zig file to a corresponding .rs file, matching PORTING.md and LIFETIMES.tsv;
  • Fix compilation errors for each crate;
  • Make subcommands like bun test or bun build run;
  • Make all tests in Bun's entire test suite pass; perform several rounds of major refactoring and cleanup.

At its peak, Sumner ran four workflows simultaneously, each containing 16 Claude instances, for a total of 64 Claude instances working in parallel across four workflow trees, each submitting and pushing files. At the peak, Claude wrote approximately 1,300 lines of code per minute.

This “implementer / reviewer” separation design is crucial. Claude, who writes the code, has the same bias as human engineers—wanting the code to be accepted. Therefore, reviewers and implementers are completely separated: reviewers examine only the code diffs, not the implementer’s reasoning, and are explicitly instructed to “assume the code is wrong.” Each implementer is assigned more than two adversarial reviewers whose sole task is to find bugs.

Writing the code is just the first step. Zig code is a single compilation unit, while Rust needs to be split into about 100 crates to speed up compilation—circular dependencies caused cargo check to output approximately 16,000 compilation errors at once. For one person, this would be a disaster, but for 64 parallel instances of Claude, it’s a manageable queue of tasks. The workflow groups errors by crate, runs cargo check for each crate, assigns one Claude to fix the issue, two to review, and one to apply the changes.

Next, run bun --version, followed by bun test. The test workflow randomly runs 100 test files, distributed across 4 worker trees. The test suite includes several types: some tests run for over a minute, some exhaust the system’s TCP connection limit, and some fork approximately 10,000 processes. Sumner used systemd-run to create cgroups to limit resources, but the machine still crashed multiple times due to insufficient disk space.

Two days later, the number of failed tests on the Linux platform dropped from 972 to 23. One and a half days after that, Linux was fully green. Five days later, all six platforms—Linux x64, Linux arm64, macOS x64, macOS arm64, Windows x64, and Windows arm64—passed successfully.

On May 14, PR #30412 was officially merged, and the test suite passed all tests without skipping or removing any.

3. Concern: 13,000 unsafe and non-line-by-line reviewable lines of code

However, Sumner also acknowledged that this work has not truly been completed.

As of now, approximately 4% of Bun’s Rust code resides within unsafe blocks, comprising about 13,000 unsafe keywords spread across roughly 27,000 lines of code, out of a total Rust codebase of approximately 780,000 lines. Of these, 78% of the unsafe blocks consist of only one line, typically involving a pointer from C++ or a single call to a C library.

He expects that subsequent refactoring will bring this ratio down. But someone did the math: UV has approximately 350,000 lines of code and only 73 unsafe calls, while Bun has 178 times more unsafe calls than UV. This disparity is hard to explain away by saying it’s simply due to calling C libraries.

And subsequently, undefined behavior was also exposed in safe Rust code. This is harder to debug than C++, because you assume safe code cannot have issues.

The Bun team then changed PathString::init in this issue to an unsafe fn.

Sumner himself acknowledged that this rewrite introduced 19 known regressions and stated that most of these regressions stemmed from code with identical syntax but different semantics.

For example, these two code snippets may look similar but behave very differently. In Zig, assert is a function, so its arguments are evaluated during every build. In Rust, debug_assert! is a macro, so in release builds, the entire expression—including the function call—is removed.

Although all the issues have been fixed, this does not mean that the million lines of AI code have no other problems.

Who in their right mind would immediately migrate their production application to a runtime that has been completely rewritten? It would be naive to assume that version 1.4 introduced no new bugs or behavioral changes.

Another thing that cannot be ignored is code review. Reviewing one million lines of changes is practically impossible for a human to do line by line—even at one line per minute, it would take 11.7 days straight; at a realistic code review pace of 200 lines per hour, it would take more than two years to complete.

The reviewers for this PR were primarily claude[bot] and coderabbitai[bot]. Sumner himself acknowledged that his review approach involved "checking whether adversarial review agents correctly captured differences, ensuring adherence to conversion guidelines, while also manually reading a significant amount of code." However, he did not specify how much "significant" actually means.

Another unavoidable issue: Bun was acquired by Anthropic in December 2025, and the only tool capable of effectively maintaining this codebase is Claude itself. Some in the community argue that this no longer qualifies as an open-source project in the traditional sense—if you want to submit a PR to Bun, you must first subscribe to Anthropic, or rely on the handful of core contributors who have already figured out the AI-generated code.

Is $165,000 worth a year’s worth of work?

Sumner also disclosed in his blog that the cost of rewriting the API was approximately $165,000, equivalent to the work of three engineers for one year. This figure sparked intense discussion on Hacker News.

Some argue that this expense is actually a great deal. In Silicon Valley, $165,000 wouldn’t hire many full-time engineers, let alone engineers from a company like Anthropic. According to salary data from levels.fyi, an Anthropic engineer’s total compensation likely reaches $500,000 or more. Even using a rough estimate of an average annual salary of $336,000 for 50 engineers, that amounts to roughly $1,292 per day per person. For 50 people working continuously for 11 days, labor costs alone would approach $710,000—not including benefits, office space, equipment, or other overhead expenses.

However, Sumner used a pre-release version of Claude 3.5, an advanced model not yet available to the public and potentially subject to export controls. Therefore, the API pricing represents only the number seen by end users, masking the substantial R&D investment made by Anthropic. Others have pointed out that reducing costs to just API pricing deliberately downplays the true scale of investment. When accounting for model development costs, training expenses, computational resources, and engineering labor, the total cost is undoubtedly very high—likely exceeding $1.5 million.

And at first glance, exchanging $165,000 for a year’s worth of work seems like a great deal.

But the real cost isn’t on this invoice. This codebase has 6,778 commits, and no one has ever read through it from start to finish. Everything works fine for now—but what about six months from now? When a strange concurrency issue suddenly pops up at 3 a.m., the on-call engineer will be faced with a system whose internal logic even he can’t fully explain. Extending this into the future, AI will have to maintain it—but how do you even calculate that maintenance cost? It’s incredibly difficult.

Disclaimer: The information on this page may have been obtained from third parties and does not necessarily reflect the views or opinions of KuCoin. This content is provided for general informational purposes only, without any representation or warranty of any kind, nor shall it be construed as financial or investment advice. KuCoin shall not be liable for any errors or omissions, or for any outcomes resulting from the use of this information. Investments in digital assets can be risky. Please carefully evaluate the risks of a product and your risk tolerance based on your own financial circumstances. For more information, please refer to our Terms of Use and Risk Disclosure.