Bun: o que ler para entender o runtime de verdade
O Hacker News reabriu o tópico de sempre: Ask HN: What are you reading?. Esses fios costumam encher de livro de ficção, biografia e algum clássico de arquitetura de software. Lendo um deles, me peguei pensando em outra coisa. O que eu mais leio hoje, fora de livro, é sobre o Bun. Uso o Bun todo dia e percebi que entendo pouco do que roda por baixo. Então aqui vai minha resposta ao Ask HN, versão dev: o que vale ler para entender o Bun de verdade, e não só repetir o bun install no automático.
Por que ler sobre o Bun em vez de só instalar?
Porque o Bun faz coisa demais em um binário só. Ele é runtime, gerenciador de pacotes, bundler, test runner e, nas versões mais recentes, cliente de Postgres, SQLite, S3 e Redis. Quando tudo funciona, ótimo. Quando algo quebra, você não sabe nem em qual dessas peças procurar.
Com Node isso é mais fácil. O erro é do npm, do Jest, do webpack ou do pg. Cada um tem seu repositório, sua issue e seu Stack Overflow. No Bun, tudo vem do mesmo lugar. Isso é conveniente, mas também é um ponto único de surpresa.
Tem também o contexto. O Bun foi comprado pela Anthropic no fim de 2025 e virou peça de infraestrutura de ferramentas de IA para código. Ele deixou de ser o projeto empolgante de um time pequeno. Hoje é dependência séria de muita gente. Vale a pena saber onde você está pisando.
Comece pelo changelog do Bun, não pelo benchmark
O benchmark é a primeira coisa que todo mundo vê. "4x mais rápido que o Node." Legal. Só que benchmark de runtime mede um hello world servindo HTTP, e o seu app passa 80% do tempo esperando o banco.
O changelog conta outra história, e é a mais útil. No blog do Bun cada release lista:
- o que ficou compatível com APIs do Node que antes faltavam
- bugs corrigidos em
node:http,node:crypto, streams - mudanças de comportamento no
bun installe no lockfile
Foi lendo changelog que eu entendi por que um teste meu falhava só no CI. Era uma diferença no comportamento de um módulo do Node que tinha sido corrigida duas versões depois da que estava fixada no pipeline. Dez minutos de leitura teriam me poupado uma tarde.
Benchmark diz quão rápido. Changelog diz quão confiável.
Minha opinião forte do dia: se você usa Bun em produção e nunca leu um changelog dele, você está confiando no marketing. Leia as últimas três releases. Leva menos tempo que um episódio de série.
O que a documentação do Bun responde que você não sabia
A documentação oficial é melhor do que parece. O problema é que a gente só abre quando já está com pressa.
Algumas páginas que valem a leitura com calma:
- Node.js compatibility: lista módulo por módulo o que está completo, parcial ou ausente. Antes de migrar um serviço, comece por aqui.
- bun install e lockfile: explica o
bun.lockem texto, que substituiu o bináriobun.lockb. Se seu time ainda tem o arquivo binário no repositório, é hora de migrar. O diff no PR agora é legível. - Bun.serve: mostra rotas, WebSocket e streaming numa API só. Muita gente sobe Express em cima do Bun sem precisar.
Um exemplo do que dá para fazer sem dependência nenhuma:
Bun.serve({
port: 3000,
routes: {
"/health": new Response("ok"),
"/users/:id": (req) => Response.json({ id: req.params.id }),
},
});
Isso substitui um Express com dois handlers. Não estou dizendo que você deve jogar o Express fora amanhã. Estou dizendo que, para um serviço pequeno, você talvez nunca precisasse dele.
Ler o código-fonte do Bun vale a pena?
Vale, com expectativa ajustada. O Bun é escrito em Zig e usa o JavaScriptCore, o motor do Safari, em vez do V8 do Node e do Deno. Você não precisa saber Zig para tirar proveito. Precisa saber onde olhar.
O repositório no GitHub tem duas partes que eu recomendo:
src/js: boa parte das APIs compatíveis com Node é escrita em TypeScript e JavaScript. Dá para ler como onode:fsou onode:eventsé implementado sem saber nada de Zig.test/: os testes mostram o comportamento esperado melhor do que qualquer doc. Quer saber se um edge case é suportado? Procure o teste.
A parte em Zig é densa. Eu leio por curiosidade, não por necessidade. Mas entender que o Bun troca o V8 pelo JavaScriptCore explica muita coisa: startup mais rápido, perfil de memória diferente e, às vezes, um comportamento de GC que não bate com o que você mediu no Node.
E se você quiser rir um pouco, procure issues antigas com o título "works in Node". É o gênero literário mais popular do repositório.
O que muda no seu projeto quando você entende o Bun
Ler sobre o Bun muda decisão concreta. Três exemplos que já mudaram aqui.
Banco de dados sem driver extra. O Bun tem cliente de SQLite e de Postgres embutidos. Para script, seed ou ferramenta interna, eu parei de instalar pg e better-sqlite3:
import { sql } from "bun";
// lê a conexão de DATABASE_URL
const ativos = await sql`select id, email from users where active = ${true}`;
import { Database } from "bun:sqlite";
const db = new Database("cache.db");
const item = db.query("select * from cache where key = ?").get("home");
Script de shell em TypeScript. O Bun.$ roda comando de shell com escape automático e funciona igual no Linux, no Mac e no Windows:
import { $ } from "bun";
const branch = (await $`git branch --show-current`.text()).trim();
await $`echo deploy da ${branch}`;
Aquele scripts/deploy.sh que só funciona na máquina de quem escreveu pode virar um .ts que todo mundo roda.
Test runner. O bun test aceita a API do Jest (describe, it, expect). Em projeto pequeno, a migração foi apagar a config do Jest e trocar o comando no package.json. Em projeto grande com mock pesado de módulo, não foi tão simples. É aí que a página de compatibilidade salva seu dia.
Onde o Bun ainda morde
Sem hype: o Bun não é Node com turbo. É outro runtime que fala a língua do Node. Na maior parte do tempo a tradução é perfeita. Às vezes não é.
Os lugares onde eu ainda vejo problema com mais frequência:
- Addons nativos: pacotes com binário compilado para o Node (N-API) costumam funcionar, mas nem sempre. Teste antes de prometer prazo.
- Ferramentas que leem internals do Node: alguns APMs e profilers dependem de detalhes do V8. No JavaScriptCore eles simplesmente não têm onde se apoiar.
- Plataforma de deploy: nem todo provedor suporta Bun nativamente. A Vercel já oferece runtime Bun para Functions, mas vale conferir o seu antes de mudar.
A regra que eu sigo é simples. Bun como gerenciador de pacotes e test runner: pode usar sem medo. Bun como runtime de produção: use, mas com teste de carga no seu caso real e com o changelog aberto em outra aba.
Minha resposta para o Ask HN
Se alguém me perguntasse no fio o que eu estou lendo, eu responderia: o changelog do Bun, a página de compatibilidade com o Node e a pasta test/ do repositório. Não é leitura de cabeceira. Mas é a que mais devolveu horas para o meu trabalho este ano.
Ferramenta que você não entende vira mágica, e mágica em produção sempre cobra a conta numa sexta à noite. Ler sobre o Bun por meia hora por mês é um seguro barato. Se quiser ver onde eu uso isso na prática, dá uma olhada nos meus projetos.
Resumo para o LinkedIn
Uso o Bun todo dia e percebi que entendia muito pouco do que roda por baixo. Ele é runtime, gerenciador de pacotes, bundler, test runner e ainda traz cliente de Postgres e SQLite. Quando algo quebra, você nem sabe em qual peça procurar. O que mais me devolveu horas este ano foi o changelog, não o benchmark. O benchmark mostra a velocidade e o changelog mostra o quanto dá para confiar. Dez minutos lendo as últimas releases teriam me poupado uma tarde inteira caçando um teste que só falhava no CI. Também leio a página de compatibilidade com o Node e a pasta test/ do repositório. Os testes explicam o comportamento esperado melhor que qualquer doc. Ferramenta que você não entende vira mágica, e em produção essa mágica cobra a conta numa sexta à noite. Escrevi o guia completo do que vale ler. Se você também usa Bun, me conta o que já te pegou de surpresa. #Bun #JavaScript #TypeScript #NodeJS #DesenvolvimentoWeb