Bun's Rust Rewrite: 11 dias, 6.778 commits e o que realmente mudou
A equipe de Bun lançou algo incomum em maio de 2026: eles substituíram todo o núcleo nativo do tempo de execução por uma versão Rust, e fizeram isso em 11 dias.
A divulgação no topo do anúncio dá o tom. Bun foi adquirido pela Anthropic em dezembro de 2025. Jarred Sumner, o criador de Bun, usou uma versão de pré-lançamento de Claude – um “modelo da classe Mythos” que eles chamam de Fable 5 – para grande parte do trabalho. Este não é um experimento mental. Bun v1.4.0, a primeira versão do Rust, está em canário agora.
Os números brutos:
- 535.496 linhas de Zig (excluindo comentários) tornaram-se uma base de código Rust
- 6.778 commits entre 3 e 14 de maio
- 1.448 arquivos
.zigportados mecanicamente para.rs - ~US$ 165.000 em gastos com API (5,9 bilhões de tokens de entrada sem cache, 690 milhões de tokens de saída)
- Pico: 64 Claudes correndo ao mesmo tempo em 4 árvores de trabalho

Bun sempre foi uma aposta Zig
Bun começou como uma porta linha por linha do transpilador JS/TS do esbuild de Go to Zig. Sumner escreveu sua primeira linha de Zig em 16 de abril de 2021, depois de ver a referência da linguagem Zig de página única no Hacker News. A versão inicial - transpiler, minifier, bundler, gerenciador de pacotes compatível com npm, executor de testes semelhante ao Jest, superfície da API Node.js - foi escrita por uma pessoa em um ano, em um apartamento apertado em Oakland, antes que os LLMs fossem úteis para esse tipo de trabalho.
Essa aposta valeu a pena. A CLI da Bun agora tem mais de 22 milhões de downloads mensais. Claude Code e OpenCode o usam como tempo de execução. Vercel, Railway e DigitalOcean fornecem suporte primário.
O escopo também era o problema.
A dívida: memória GC ao lado da memória manual
JavaScript é coletado como lixo. Bun incorpora JavaScriptCore (o mecanismo do Safari) além de uma pilha de bibliotecas C/C++: uWebSockets, BoringSSL, SQLite, lsquic. Zig, como C, não gerencia memória para você. O trabalho de Bun é ficar entre uma linguagem de GC e um código nativo gerenciado manualmente, e esse limite é onde reside a maioria de seus piores bugs.
O anúncio lista uma amostra do que eles corrigiram apenas na v1.3.14: um heap-use-after-free em node:zlib, use-after-free em node:http2 de retornos de chamada reentrantes, gravações fora dos limites em UDPSocket.sendMany, um vazamento de memória por tls.connect, uma liberação dupla no analisador CSS. A lista continua e é técnica.
Sumner deixa claro que isso não é culpa de Zig. “Não teríamos chegado tão longe se não fosse por Zig, e sempre serei grato.” O problema é estrutural: lidar com tempos de vida através de um limite de GC é difícil em qualquer linguagem que não seja projetada para isso, e a resposta de Zig - defer explícita em cada site de chamada - é fácil de errar em caminhos de erro raramente alcançados.
Ele pesou C++. Cerca de 20% do Bun já é C++, e mover mais daria construtores e destruidores. Mas ainda dependeria de guias de estilo aplicados por meio de revisão de código, e a corrupção da memória ainda ocorreria.
A abordagem do Rust é diferente: no Rust seguro, use-after-free, double-free e “esqueci de liberar” são erros do compilador. O verificador de empréstimo e Drop transformam um problema de guia de estilo em um problema de sistema de tipos.
A estratégia: transpilar, não redesenhar
As reescritas têm má reputação e por boas razões. Uma reescrita do zero de 535 mil linhas congelaria recursos e correções por um ano. O formato escolhido por Bun foi uma porta mecânica: mesma arquitetura, mesmas metas de desempenho, mesmos recursos, mesmo conjunto de testes – apenas em Rust.
Duas decisões orientaram todo o esforço:
- Tudo de uma vez, não incremental. A experiência de Sumner ao portar esbuild para Zig disse a ele que reescritas incrementais deixam uma estrutura temporária que prejudica mais do que ajuda.
- Faça com que pareça transpilado. O objetivo era Rust que se parece com o Zig de onde veio, para ser refatorado em direção ao Rust idiomático após o lançamento da v1.4.
Crucialmente, o conjunto de testes do Bun é escrito em TypeScript, então ele não se importa em qual linguagem o tempo de execução é implementado. Isso permite que eles tratem “todos os testes verdes” como a definição de concluído.
A preparação foi pequena, mas deliberada. Antes de escrever o código, Sumner passou cerca de 3 horas com Claude mapeando padrões Zig para Rust; essa conversa se tornou PORTING.md (mais tarde chegou ao Hacker News). Uma segunda passagem analisou os tempos de vida adequados do Rust de cada campo struct na base de código e os serializou em LIFETIMES.tsv. Ambos os documentos passaram por revisão contraditória antes de uma única linha ser portada.
O que ficou parado: JavaScriptCore e as bibliotecas C/C++ incorporadas. A reescrita foi a cola nativa e o código específico do Bun, não o mecanismo JS.
Execução: 64 Claudes, 11 diasA porta funcionou cerca de 50 “fluxos de trabalho dinâmicos” no Claude Code, continuamente, durante 11 dias. Cada fluxo de trabalho era um ciclo: pegar uma tarefa, produzir código, revisá-lo, aplicar feedback.
O modelo de revisão é a parte interessante. Para cada implementador, havia dois ou mais revisores adversários – sessões separadas de Claude instruídas a assumir que o código está errado e a encontrar todos os motivos pelos quais ele falhou. O implementador nunca revisa; o revisor nunca implementa. O anúncio enquadra isso como um reflexo da revisão humana: o autor deseja fundir, então uma parte diferente verifica.
Vale a pena retirar algumas mecânicas:
- Teste primeiro. Eles portaram 3 arquivos antes de enviar para todos os 1.448.
- Fragmentação da árvore de trabalho. As primeiras execuções fizeram com que Claudes se atropelassem com
git stashegit reset. A solução: 4 árvores de trabalho, 16 Claudes cada, com uma regra para nunca executar git ou cargo no meio da tarefa. - Erros do compilador como uma fila de trabalho.
cargo checkdespejou cerca de 16.000 erros em um arquivo, agrupados por caixa, e 64 Claudes eliminados — 16 loops de correção/revisão/aplicação em 4 árvores de trabalho. - Dependências cíclicas. Zig era efetivamente uma unidade de compilação; A ferrugem precisava de cerca de 100 caixas. Desembaraçar os ciclos trouxe à tona a maioria desses 16.000 erros.
- Isolamento. Testes de estresse que esgotam os soquetes TCP ou geram cerca de 10 mil processos executados em
systemd-runcgroups. A máquina ainda ficou sem disco e travou algumas vezes.
timeline
title Bun's 11-day Zig → Rust rewrite (May 2026)
2026-05-03 : Port branch opened (PR #30412)
2026-05-04 : First 100-file draft batch
2026-05-06 : ~16,000 compiler errors, 64 Claudes
2026-05-08 : First CI run (972 failing files)
2026-05-09 : Linux x64 turns green
2026-05-11 : Windows green (last platform)
2026-05-14 : All 6 platforms green, merged
Pelos números: pico de 1.300 linhas de código por minuto, 695 commits na hora de maior movimento (6 de maio), 58 commits no único minuto de maior movimento. Cada commit foi revisado por dois revisores adversários antes do lançamento. A diferença final foi de +1.009.272 linhas. Nenhum teste foi ignorado ou excluído.
CI é onde isso se tornou real. Dois dias após a primeira execução, os arquivos de teste com falha caíram de 972 para 23. Um dia e meio depois, o Linux ficou totalmente verde. O Windows terminou em 11 de maio; todas as seis plataformas eram verdes na versão 54202, 14 de maio.
O que Rust realmente comprou
O objetivo declarado era a estabilidade, e o post apoia isso com números concretos.
Bugs. Bun v1.4.0 corrige 128 bugs que se reproduzem na v1.3.14.
Memória. Drop substituída por site de chamada defer. O exemplo da postagem: agrupar o mesmo projeto de 60 módulos 2.000 vezes em um processo. Na v1.3.14, cada compilação vaza aproximadamente 3 MB para sempre; na versão 1.4.0, a memória está desligada.
| Construções | v1.3.14 | v1.4.0 |
|---|---|---|
| 500 | 1.914MB | 526 MB |
| 1.000 | 3.506MB | 586MB |
| 1.500 | 5.097MB | 608MB |
| 2.000 | 6.745 MB | 609 MB |
Uma tentativa anterior de corrigir isso no Zig nunca foi mesclada, escreve Sumner, porque a falta de um equivalente Drop tornava difícil se sentir confiante.
Tamanho binário. Somente a reescrita do Rust cortou 3,8 MB (Windows), 5,5 MB (macOS), 6,8 MB (Linux) – principalmente devido à eliminação excessiva do Zig comptime. O trabalho adicional do vinculador (dobragem de código idêntico, corte de dados da UTI) trouxe redução total para aproximadamente 20% no Linux e Windows.
| Versão | Plataforma | Tamanho |
|---|---|---|
| v1.4.0 | Janelas | 76 MB |
| v1.3.14 | Janelas | 94 MB |
| v1.4.0 | Linux | 70 MB |
| v1.3.14 | Linux | 88 MB |
Velocidade. LTO entre linguagens entre C/C++ e Rust permite que o compilador inline através dos limites da linguagem. Bun mediu ganhos de 2–5%:
Bun.serve: 169,6k → 177,7k req/s (+4,8%)express: 64,5 mil → 66,6 mil (+3,2%)next build: 13,62s → 13,03s (+4,5%)tsc -b --force: 0,94s → 0,89s (+4,7%)
Prisma mudou seu beta público do Compute para a reescrita do Rust. Alexey Orlenko: “Encontramos vazamentos de memória e um pool de conexões que não pôde ser recuperado depois que uma VM foi pausada e retomada. Quando a reescrita do Rust apareceu, nós a testamos nos mesmos modos de falha. Ela os tratou perfeitamente.”
Claude Code v2.1.181 (17 de junho) e posteriormente usa a porta Rust. A inicialização é 10% mais rápida no Linux. O veredicto de Sumner sobre a mudança visível ao usuário: “Chato é bom.”
Onde o porto escorregou
Uma transpilação fiel de 535 mil linhas não é gratuita. A postagem documenta 19 regressões conhecidas, todas corrigidas. Os instrutivos são pequenas lacunas semânticas entre os idiomas:- debug_assert! efeitos colaterais. assert do Zig é uma função, então seu argumento é executado em cada compilação. O debug_assert! de Rust é uma macro apagada no lançamento - uma chamada insert_stale que o estado HMR mutado parou de funcionar silenciosamente. (#30678)
- Fatias de comprimento ímpar. O ajudante de Zig ignorou um byte ímpar final;
bytemuck::cast_sliceentra em pânico com isso.Blob.text()em uma BOM UTF-16 mais uma contagem de bytes ímpar começou a travar. (#31188) - Verificações de limites. O
ReleaseFastde Zig os remove; A ferrugem os mantém. Uma constante de espaço reservado reduziu o limite de internação de nomes de arquivos de 8,4 milhões para 270 mil, e projetos reais atingiram esse limite. (#31503) comptimestrings de formato. Zig avalia strings de formato em tempo de compilação, portanto, os marcadores de cores desaparecem antes que os argumentos sejam substituídos. Rust não temcomptime, então o analisador de marcador comeu uma barra invertida literal nos hiperlinks OSC 8. (#30693)
Esses são os bugs que só surgem porque dois idiomas parecem idênticos, mas não são.
O que isso significa
Retire o ângulo do LLM e há uma verdadeira história de engenharia: um projeto atingiu o limite do que o gerenciamento manual de memória poderia oferecer em escala e escolheu o verificador de empréstimos de Rust como a ferramenta para tornar impossível uma classe inteira de bugs, em vez de apenas desencorajá-los.
O ângulo LLM é a parte sobre a qual as pessoas discutirão. Sumner é sincero ao dizer que isso levaria cerca de um ano para três engenheiros com o contexto completo da base de código, e que eles nunca teriam feito isso - a alternativa realista era “não fazer nada e continuar corrigindo os bugs”. Em vez disso, um engenheiro supervisionando 64 Claudes fez isso em 11 dias por aproximadamente US$ 165 mil.
Cerca de 4% do código Rust de Bun está em blocos unsafe (~13.000 palavras-chave unsafe em ~27.000 linhas de ~780.000 no total), e 78% desses blocos são uma única linha. Desde a fusão, eles realizaram 11 rodadas de revisão de segurança e adicionaram difusão guiada por cobertura 24 horas por dia, 7 dias por semana, em cada analisador – 100 bilhões de execuções até agora, aproximadamente 15 PRs.
A questão da manutenção é a que eu observaria. Sumner diz que o Rust se parece com o Zig e mostra lado a lado de canMergeSymbols para deixar claro. A aposta é que uma porta fiel pode ser revisada porta por porta, o que permite que uma pessoa assine uma diferença de um milhão de linhas.
Sua frase final é aquela que envelhecerá de maneira interessante: “Um engenheiro pode fazer muito mais hoje do que há um ano.”