El proyecto Bun completó en mayo de 2026 una migración importante del código de Zig a Rust, realizando más de 1 millón de líneas de cambios y 6.778 commits en 11 días. La migración utilizó 64 instancias de Claude trabajando en paralelo, con un costo de API de $165.000. Tras la migración, se resolvieron fundamentalmente los problemas de fugas de memoria: tras 2.000 compilaciones, la memoria se estabilizó desde 6,7 GB hasta 609 MB, con un aumento de rendimiento del 2% al 5% y una reducción del tamaño del archivo binario de aproximadamente un 20%. Sin embargo, el código contiene aproximadamente 13.000 palabras clave unsafe, 178 veces más que en proyectos similares; se conocen 19 problemas de regresión, y los 1 millón de líneas modificadas no pudieron ser revisadas línea por línea por humanos. Actualmente, Bun ha sido adquirido por Anthropic.Autor y fuente del artículo: InfoQ
En mayo de 2026, el proyecto Bun completó una migración de código a gran escala, casi inédita en la historia del desarrollo de software.
Esta migración comenzó el 3 de mayo y se fusionó oficialmente en la rama principal el 14 de mayo, solo tardó 11 días. Escribir el código tomó solo 6 días, y todo el proceso fue público. Sin embargo, a Jarred Sumner le tomó casi un mes escribir su entrada de blog resumiendo el proceso, mucho más tiempo del que tardó en escribir el código.
Este entorno de ejecución de JavaScript originalmente tenía 535,496 líneas de código Zig, sin incluir comentarios; además, aproximadamente el 20% del código estaba escrito en C++ e integraba múltiples bibliotecas C/C++. Esta reescritura con ayuda de IA a Rust implicó más de 1 millón de líneas de cambio, 6,778 commits y la ejecución de aproximadamente 50 flujos de trabajo dinámicos en Claude Code.
Según los datos revelados por Sumner, esta reescritura consumió 5.9 mil millones de tokens de entrada no almacenados en caché, 690 millones de tokens de salida y 72 mil millones de lecturas de tokens de entrada almacenados en caché, lo que representa un costo aproximado de $165,000 según los precios de la API.
Sumner dijo que esto representa el límite actual de lo que la tecnología puede lograr. Estimó que, si tres ingenieros completamente familiarizados con la base de código de Bun realizaran esta migración manualmente, les tomaría aproximadamente un año, y durante ese tiempo, el equipo casi no podría avanzar en el desarrollo de nuevas funciones, la corrección de errores ni las actualizaciones de seguridad.
Después de esta reescritura, Bun v1.3.14 será la última versión en Zig, y Bun v1.4.0 será la primera versión en Rust.
1 Resultado: De 6,7 GB de fuga de memoria a 609 MB estables
Bun comenzó como un proyecto Zig con un alcance muy amplio: es al mismo tiempo un transpilador de JavaScript y TypeScript, un empaquetador, un administrador de paquetes, un ejecutor de pruebas, un resolvedor de módulos, un cliente HTTP y WebSocket, e implementa la capa de API de Node.js. Esta amplia gama de funcionalidades ha llevado a que el CLI de Bun tenga más de 22 millones de descargas mensuales y haya recibido el apoyo de proyectos o empresas como Vercel, Railway, DigitalOcean, Claude Code y OpenCode.
Pero este mismo ancho también presenta algunos desafíos para Bun.
En particular, en Bun v1.3.14, existe un problema que ha causado molestias durante mucho tiempo: al ejecutar llamadas consecutivas a Bun.build(), la memoria se acumula continuamente y nunca se libera. Cada construcción fuga aproximadamente 3 MB, lo que parece poco, pero si estás ejecutando un servidor de desarrollo donde cada solicitud activa una construcción, la memoria se consumirá gradualmente hasta que el proceso colapse.
En las pruebas reales, el uso de memoria fue de 1.9 GB después de 500 compilaciones, 3.5 GB después de 1000, 5.1 GB después de 1500 y aumentó a 6.7 GB después de 2000.

Esto es solo la punta del iceberg de muchos problemas de memoria. En la lista de correcciones de errores de la v1.3.14, Sumner enumeró una larga lista de problemas:
Al llamar a .reset() en el módulo zlib, si aún hay un .write() asincrónico en ejecución en el grupo de hilos, el proceso se bloquea debido a "uso después de liberar el heap"; en el módulo http2, los callbacks anidados de JavaScript desencadenan una rehashing de la tabla hash, lo que provoca la invalidez de los punteros internos de flujo; en UDPSocket.sendMany(), si el código del usuario modifica el estado de conexión del socket mediante callbacks de valueOf o toString durante la iteración, se produce una escritura fuera de límites; cuando crypto.scrypt falla en la asignación del buffer de salida, el callback y el buffer protegido de la contraseña nunca se liberan; ......La característica común de estos errores es muy clara: casi todos apuntan a la misma causa raíz: combinar GC con gestión manual de memoria en el mismo software.
Motoras modernas como JavaScriptCore (y V8) tienen reglas extremadamente estrictas para el manejo de excepciones y GC, mientras que Zig, como C, no gestiona la memoria automáticamente. Cuando estos dos paradigmas coexisten en el mismo proceso, cada asignación de memoria debe ser revisada línea por línea: ¿dónde se liberan estos bytes? ¿Cómo se asegura que se liberen solo una vez? ¿Se verifican correctamente las excepciones de JavaScript? ¿Es visible este puntero gestionado por GC para el escáner conservador de la pila? ¿Es memoria gestionada por GC o memoria gestionada manualmente?
Lo que es aún más preocupante es que el equipo no ha dejado de esforzarse. Ya han modificado el compilador Zig para agregar soporte de Address Sanitizer (ASAN), ejecutan pruebas ASAN en CI en cada confirmación, construyen con ReleaseSafe en Windows, realizan pruebas de fuzzing 24/7 con Fuzzilli y llevan a cabo numerosas pruebas de fuga de memoria de extremo a extremo. A pesar de todo esto, los informes de errores continúan llegando sin cesar.
“Nuestra lista de correcciones de errores nos hace sentir muy mal; estoy cansado de dormir con la preocupación de que Bun se bloquee,” escribió Sumner. Él no culpa a Zig: otros usuarios de Zig no han experimentado problemas con Bun, ya que combinar GC con memoria gestionada manualmente es una necesidad extremadamente rara, y casi ningún lenguaje está diseñado para ello.
La versión en Rust presenta un rendimiento de: al ejecutar 2000 veces Bun.build(), la memoria se mantiene estable en 609 MB.
Además de que el problema de fugas de memoria se resolvió de forma fundamental, la reescritura en Rust también trajo mejoras en varios otros aspectos.
En términos de estabilidad, la v1.4.0 corrige 128 errores reproducibles de la v1.3.14, abordando problemas desde fugas de memoria hasta bloqueos y errores de color en los textos de ayuda.
En términos de tamaño, combinando la reescritura en Rust, los cambios en ICU y la misma compresión de código, el tamaño binario de Bun se redujo aproximadamente un 20 % en Linux y Windows.

En términos de rendimiento, se mejoró generalmente entre un 2% y un 5%. Bun.serve aumentó de 169.600 req/s a 177.700 req/s, y node:http pasó de 103.800 a 108.500. En escenarios de uso real, next build disminuyó de 13.62 segundos a 13.03 segundos, y la compilación por lotes de tsc pasó de 0.94 segundos a 0.89 segundos.
Después del lanzamiento de Claude Code basado en Rust Bun, el tiempo de inicio en Linux disminuyó de 517 ms a 464 ms, un 10 % más rápido.

2 métodos: 64 Claude, 11 días, 50 flujos de trabajo
¿Cómo lo hizo Sumner? Esta podría ser la parte más importante de todo: porque su método es diferente al tradicional "hacer que la IA escriba código".
Sumner dividió todo el proceso en aproximadamente 50 flujos de trabajo dinámicos, cada uno de los cuales es un bucle. En su blog, describió este patrón con pseudocódigo:

Cada tarea tiene un contexto (por ejemplo, un ticket de Jira o un issue de GitHub), Claude escribe el código basándose en ese contexto, luego dos revisores (también Claude) revisan el código y finalmente se aplican los comentarios. Una vez completado, se toma la siguiente tarea.
Este patrón se mantiene a lo largo de todo el proceso de reescritura. Cada flujo de trabajo se encarga de un objetivo específico:
- Generate a porting guide that maps Zig's patterns and types to Rust's patterns and types;
- Mueva mecánicamente cada archivo .zig a un archivo .rs, y empareje con PORTING.md y LIFETIMES.tsv;
- Corregir los errores de compilación de cada crate;
- Hacer que los subcomandos como bun test o bun build funcionen;
- Haz que todas las pruebas en la suite de pruebas de Bun pasen; realiza varias rondas de reestructuración y limpieza importantes.
Durante el pico, Sumner ejecutó simultáneamente 4 flujos de trabajo, cada uno con 16 Claude, lo que sumó un total de 64 Claude trabajando en paralelo en 4 árboles de trabajo, enviando y empujando archivos individualmente. En el punto más alto, Claude escribió aproximadamente 1300 líneas de código por minuto.
Este diseño de separación entre "implementador" y "revisor" es clave. Claude, al escribir el código, quiere que este sea aceptado, al igual que los ingenieros humanos, lo que introduce sesgos. Por eso, revisores e implementadores están completamente separados: los revisores solo examinan las diferencias del código, sin ver el razonamiento del implementador, y se les indica explícitamente que "asuman que el código es incorrecto". Cada implementador tiene asignados más de dos revisores adversariales, cuyo único trabajo es encontrar errores.

Escribir el código es solo el primer paso. El código Zig es una unidad de compilación única, mientras que Rust debe dividirse en aproximadamente 100 crates para acelerar la compilación; las dependencias cíclicas provocan que cargo check genere alrededor de 16,000 errores de compilación de una sola vez. Para una persona, esto sería un desastre, pero para 64 Claudes trabajando en paralelo, es una cola de trabajo manejable. El flujo de trabajo agrupa los errores por crate, ejecuta cargo check para cada crate, un Claude corrige, dos revisan y uno aplica los cambios.
A continuación, ejecuta bun --version y luego bun test. El flujo de pruebas ejecuta aleatoriamente 100 archivos de prueba, distribuidos en 4 árboles de trabajo. La suite de pruebas también incluye varios tipos: algunas pruebas duran más de un minuto, otras agotan el número de conexiones TCP del sistema, y algunas fork aproximadamente 10,000 procesos. Sumner usó systemd-run para crear cgroups que limitan los recursos, pero la máquina aún se colapsó varias veces por falta de espacio en disco.
Dos días después, las pruebas fallidas en la plataforma Linux disminuyeron de 972 a 23. Un día y medio después, Linux estaba completamente verde. Cinco días después, los seis plataformas completas —Linux x64, Linux arm64, macOS x64, macOS arm64, Windows x64, Windows arm64— pasaron todas.
El 14 de mayo, PR #30412 se fusionó oficialmente, y todas las pruebas del conjunto se aprobaron sin omitir ni eliminar ninguna prueba.

3 Preocupaciones: 13,000 líneas de código inseguras e imposibles de revisar línea por línea
Sin embargo, Sumner también reconoce que este trabajo aún no ha terminado realmente.
Hasta la fecha, aproximadamente el 4% del código Rust de Bun se encuentra dentro de bloques unsafe, con alrededor de 13,000 palabras clave unsafe distribuidas en aproximadamente 27,000 líneas de código, mientras que el código Rust total asciende a aproximadamente 780,000 líneas. El 78% de los bloques unsafe tienen solo una línea, generalmente un puntero proveniente de C++ o una llamada a una biblioteca C.
Él espera que la reestructuración futura reduzca esta proporción. Pero alguien hizo un cálculo: uv tiene aproximadamente 350,000 líneas de código y solo 73 llamadas unsafe. La cantidad de unsafe en Bun es 178 veces mayor que la de uv. Esta diferencia es difícil de explicar con solo "la necesidad de llamar a bibliotecas C".
Y luego también se expuso comportamiento indefinido en código Rust seguro. Es más difícil de depurar que en C++, porque uno asume que el código seguro no puede tener errores.

El equipo de Bun luego cambió PathString::init en este problema a una función unsafe.
Sumner también reconoció que esta reescritura introdujo 19 problemas de regresión conocidos y señaló que la mayoría de los problemas de regresión provienen de código con la misma sintaxis pero diferente semántica.

Por ejemplo, estos dos fragmentos de código parecen similares, pero su comportamiento es completamente diferente. La afirmación de Zig, assert, es una función, por lo que sus parámetros se ejecutan en cada compilación. El código de Rust, debug_assert!, es un macro, por lo que en las versiones de lanzamiento, toda la expresión (incluida la llamada a la función) se elimina insert_stale.
Aunque se han solucionado todos los problemas, esto no significa que el millón de líneas de código de IA no tengan otros problemas.

¿Quién en su sano juicio migraría su aplicación de producción inmediatamente después de que se haya reescrito por completo en tiempo de ejecución? Creer que la versión 1.4 no introdujo nuevos errores ni cambios de comportamiento es demasiado ingenuo.Otro aspecto que no se puede ignorar es la revisión de código. Revisar 1 millón de líneas de cambio es imposible de hacer manualmente: incluso a una línea por minuto, tomaría 11.7 días continuos; a la velocidad real de revisión de código (200 líneas por hora), tomaría más de dos años terminarla.
Los revisores de esta PR fueron principalmente claude[bot] y coderabbitai[bot]. Sumner también admitió que su método de revisión consistía en "verificar si el agente de revisión adversarial capturó correctamente las diferencias, asegurarse de que se siguieran las pautas de conversión, mientras leía manualmente una buena cantidad de código". Pero no especificó cuánto es "una buena cantidad".
Aún hay otro problema inevitable: Bun fue adquirido por Anthropic en diciembre de 2025, y la única herramienta realmente capaz de mantener eficazmente este repositorio es Claude en sí mismo. Algunos miembros de la comunidad dicen que ya ni siquiera se puede considerar un proyecto de código abierto en el sentido tradicional: si quieres enviar un PR a Bun, primero debes suscribirte a Anthropic o confiar en unos pocos miembros clave que ya han entendido el código generado por IA.
¿Vale la pena 165.000 dólares por un año de trabajo?
Sumner también reveló en su blog que el costo de esta reescritura de la API fue de aproximadamente 165.000 dólares, equivalente al trabajo de tres ingenieros durante un año. Este número generó un intenso debate en Hacker News.
Algunos consideran que esta cuenta en realidad es muy rentable. En Silicon Valley, 165.000 dólares no contratan a muchos ingenieros de tiempo completo, mucho menos ingenieros de una empresa como Anthropic. Según los datos salariales de levels.fyi, la compensación total de un ingeniero de Anthropic probablemente alcance los 500.000 dólares o más. Incluso calculando de forma aproximada un salario anual promedio de 336.000 dólares para 50 ingenieros, eso equivale a aproximadamente 1.292 dólares por día. Para 50 personas trabajando continuamente durante 11 días, solo el costo laboral ya se acerca a 710.000 dólares, sin incluir beneficios, espacios de oficina, equipos y otros gastos administrativos.

Sin embargo, Sumner utilizó una versión prelanzada de Claude Fable 5, un modelo avanzado que aún no está disponible para el público y que posiblemente está sujeto a restricciones de exportación. Por lo tanto, el precio de la API es solo el número que ven los usuarios finales, detrás del cual hay enormes inversiones en investigación y desarrollo por parte de Anthropic. Algunos señalan que reducir los costos al precio de la API es una forma deliberada de minimizar la verdadera inversión. Si se incluyen los costos de desarrollo del modelo, entrenamiento, infraestructura de cómputo y mano de obra de ingeniería, se cree que el costo total final será muy elevado, probablemente superando los 1,5 millones de dólares.

Y por ahora, aunque 165.000 dólares por un año de trabajo parecen una buena operación en papel.
Pero el verdadero costo no aparece en esta factura. Este repositorio tiene 6778 confirmaciones, y nadie ha leído completamente todo el código desde el principio hasta el final; aunque ahora todo funcione correctamente, ¿qué pasará dentro de seis meses? Cuando un extraño problema de concurrencia surja repentinamente a las tres de la mañana, el ingeniero de guardia se enfrentará a un sistema cuya lógica interna ni siquiera él puede explicar claramente. Extenderlo hacia el futuro significa que deberá ser mantenido por IA; ¿cómo se calcula ese costo de mantenimiento? En realidad, es bastante difícil.

