Bun nunca prometió reemplazar a Node.js al 100% — ¿Eso es bueno o malo?
Bun nunca prometió reemplazar a Node.js al 100% — ¿Eso es bueno o malo?
TL;DR: Bun apunta a 90% de compatibilidad con Node.js, no 100%. Funciona bien para APIs simples con Express/Hono, CLIs, y proyectos nuevos. Puntos de fricción: Next.js funciona como package manager pero el runtime tiene edge cases en producción; Prisma requiere Node.js instalado para el CLI; Playwright/Puppeteer problemáticos en Windows; crypto 10-14x más lento. Audita tu stack antes de migrar—las regresiones entre versiones son reales.
Si has estado siguiendo el ecosistema JavaScript en los últimos años, probablemente has escuchado que Bun es “el reemplazo de Node.js”. Más rápido, más moderno, todo-en-uno. La promesa suena irresistible: cambia node por bun y tu aplicación vuela.
Pero hay un problema. Esa promesa nunca existió exactamente así.
En este artículo vamos a investigar qué prometió realmente Bun, cuál es el estado actual de compatibilidad, y—lo más importante—si puedes confiar en él para tu stack específico. Spoiler: la respuesta depende mucho de lo que estés construyendo.
La promesa que nunca existió
Desde su lanzamiento en 2022, Bun se posicionó como un “drop-in replacement” para Node.js. Jarred Sumner, su creador, lo describió así en una entrevista con JavaScript Jabber:
“Está diseñado como un reemplazo directo de Node.js. Aún no estamos al 100%. Estamos reimplementando básicamente todas las APIs de Node.js desde cero. Es una montaña de trabajo. Pero hemos hecho mucho progreso.”
La palabra clave aquí es “aún”. Bun nunca prometió compatibilidad total desde el día uno—prometió trabajar hacia ella. Pero aquí está el detalle que muchos pasan por alto: según el roadmap oficial de Bun, el objetivo es 90% de compatibilidad, no 100%.
¿Por qué 90%? Porque algunas APIs de Node.js simplemente no tienen sentido en la arquitectura de Bun. node:v8 es el ejemplo obvio—Bun usa JavaScriptCore (el motor de Safari), no V8.
El cambio silencioso de enfoque
Si observas la evolución de Bun, notarás algo interesante. Mientras la comunidad esperaba que cada release cerrara más gaps de compatibilidad con Node.js, Bun empezó a construir cosas completamente nuevas:
- Bun.sql: Cliente nativo de PostgreSQL, MySQL y SQLite (introducido en v1.2, expandido en v1.3)
- Bun.s3: Cliente nativo de S3 (5x más rápido que
@aws-sdk/client-s3) - Bun.redis: Cliente nativo de Redis/Valkey (introducido en v1.2.9, destacado en v1.3)
- HTML Imports: Una feature que Node.js no tiene (experimental en v1.1.44, oficial en v1.2)
- Hot reloading integrado: Sin necesidad de nodemon (mejorado en v1.3)
Esto no es necesariamente malo. Pero sí revela una verdad incómoda: Bun no está tratando de ser “Node.js pero rápido”—está construyendo algo diferente.
El factor Anthropic
En diciembre de 2025, Anthropic adquirió Bun. Jarred Sumner explicó que Bun ahora potencia Claude Code, Claude Agent SDK, y otros productos de IA.
Las promesas post-adquisición:
- Bun sigue siendo open-source y MIT
- El mismo equipo continúa el desarrollo
- El roadmap mantiene el foco en compatibilidad con Node.js
Pero ahora hay un stakeholder con intereses específicos. Anthropic necesita velocidad, estabilidad, y sí—compatibilidad con Node.js. Eso podría ser bueno para todos. O podría significar que las prioridades se alineen más con las necesidades de productos de IA que con el ecosistema general.
El estado real de compatibilidad
Dejemos los titulares y veamos los números. Bun ejecuta el test suite de Node.js antes de cada release. Según la documentación oficial de compatibilidad, estos son los resultados por módulo:
Módulos con alta compatibilidad (>95%)
| Módulo | Test Suite Pass Rate |
|---|---|
node:events | 100% |
node:os | 100% |
node:path | 100% |
node:zlib | 98% |
node:http2 | 95.25% (test suite de gRPC) |
node:dns | >90% |
node:dgram | >90% |
Nota: gRPC (Google Remote Procedure Call) es un framework de comunicación entre servicios que depende fuertemente de HTTP/2. Bun usa el test suite de gRPC como benchmark para validar su implementación de node:http2 porque representa casos de uso reales y exigentes del protocolo.
Módulos con compatibilidad media (80-95%)
| Módulo | Test Suite Pass Rate | Notas |
|---|---|---|
node:fs | 92% | Falta fs.openAsBlob en algunas versiones |
node:streams | 82% | Comportamiento edge-case diferente |
node:http | ~85% | Request body se bufferea en lugar de streamear |
Nota: fs.openAsBlob permite leer archivos directamente como objetos Blob, útil para subir archivos a APIs web o procesarlos con Web Streams sin cargarlos completamente en memoria.
Lo que falta completamente
Estos módulos no están implementados, y aunque no los uses directamente, probablemente alguna dependencia en tu proyecto sí:
-
node:inspector: No implementado. Bun tiene su propio debugger con WebKit Inspector Protocol (--inspect), pero la API de Node.js no está disponible.- Paquetes afectados: Sentry (monitoreo de errores), elastic-apm-node (Elastic APM), y otras herramientas de monitoreo que dependen de este módulo para profiling.
-
node:repl: No implementado. Bun tiene su propio REPL básico (bun repl), pero no expone la API programática de Node.js.- Paquetes afectados: Vorpal (framework para CLIs interactivas), y herramientas que crean interfaces REPL personalizadas.
-
node:sqlite: Irónico dado que Bun tiene SQLite nativo (bun:sqlite), pero la API de Node.js no está implementada.- Paquetes afectados: better-sqlite3 tiene problemas de ABI incompatible—el módulo fue compilado contra una versión de Node.js diferente. Workaround: instalar con
npm installen lugar debun install, o migrar abun:sqlitedirectamente.
- Paquetes afectados: better-sqlite3 tiene problemas de ABI incompatible—el módulo fue compilado contra una versión de Node.js diferente. Workaround: instalar con
-
node:trace_events: No implementado. Solo existe un stub vacío—funciones que existen para que el código no falle al importar el módulo, pero no hacen nada. Esto evita errores de “module not found” pero el tracing simplemente no funciona.- Paquetes afectados: dd-trace (Datadog APM) y otras herramientas de tracing distribuido. Workaround: usar OpenTelemetry como alternativa para enviar traces a Datadog.
Limitaciones críticas en módulos parciales
node:cluster (documentación)
- El load-balancing solo funciona en Linux via
SO_REUSEPORT - En macOS y Windows, las conexiones no se distribuyen correctamente entre workers—es una limitación del sistema operativo, no de Bun
node:child_process (Issue #6743)
- No puede enviar socket handles via IPC—el argumento
sendHandleesundefined - Esto rompe patrones comunes de arquitectura multi-proceso donde el padre distribuye conexiones a workers
node:http2 (documentación)
- Cliente y servidor implementados (95.25% del test suite de gRPC pasa)
- Falta
http2stream.pushStream(HTTP/2 Server Push) - Falta soporte para la extensión ALTSVC
- Falta
options.allowHTTP1yoptions.enableConnectProtocol
node:crypto — El elefante en la sala
Las funciones de crypto en Bun son significativamente más lentas que en Node.js. Múltiples issues documentan el problema:
- AES-128-GCM 10x más lento: Benchmark de 1000 operaciones de encriptación
- PBKDF2 13x más lento: 237ms en Node vs 3189ms en Bun (600,000 rounds)
- RSA 14x más lento: privateEncrypt/publicDecrypt toma ~1s en Node vs ~14.5s en Bun
Si tu aplicación hace hashing intensivo, encriptación, o cualquier trabajo criptográfico pesado—no uses Bun.
La prueba de fuego: ¿Funciona tu stack?
Los números de test suites están bien, pero lo que realmente importa es: ¿funcionan los paquetes que uso todos los días?
Investigué 14 paquetes populares en diferentes industrias. Aquí está el veredicto:
Frameworks Web
Express
| Métrica | Resultado |
|---|---|
| ¿Funciona? | ✅ Sí |
| Performance | 3x más rápido que en Node.js |
| Memoria | ~2x más uso de RAM |
Fastify
| Métrica | Resultado |
|---|---|
| ¿Funciona? | ✅ Sí, pero… |
| Performance | Más lento que en Node.js en algunos benchmarks |
| Recomendación | Usa Bun.serve() directamente (3-4x más rápido) |
Jarred Sumner lo dijo directamente:
“Fastify no es rápido en Bun. Bun.serve() es 3x-4x más rápido.”
NestJS — Oficialmente soportado, pero con matices
Jarred Sumner abrió el issue #1641 para trackear la compatibilidad con NestJS. Ese issue está cerrado como COMPLETED, lo que significa que Bun considera que tiene la compatibilidad necesaria para ejecutar NestJS.
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Decorators | ✅ Sí | Desde Bun 1.0.3 |
| Core features | ✅ Sí | Issue oficial cerrado como completado |
| TypeORM integration | ⚠️ Variable | require('module').globalPaths causaba problemas (arreglado en canary builds) |
| Producción bajo carga | ⚠️ Reportes mixtos | Crashes reportados en algunos casos |
Contexto importante: El equipo de NestJS no ha declarado soporte oficial para Bun. Esto significa que si encuentras bugs, puede que ninguno de los dos equipos los priorice. Sin embargo, la comunidad ha reportado éxito en proyectos de producción.
Hono
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Todo | ✅ Sí | Diseñado para Bun |
Next.js — El caso más complejo
La situación de Next.js ha cambiado significativamente. En enero 2025, Bun removió la advertencia de incompatibilidad que decía “Next.js App Router is incompatible with Bun”.
| Uso | ¿Funciona? | Detalle |
|---|---|---|
| Package manager | ✅ Sí | bun install, bun run build funcionan perfectamente |
| Runtime (desarrollo) | ⚠️ Variable | Hot reload inconsistente reportado |
| Runtime (producción) | ⚠️ Con issues | Meta tags en <body> al refrescar (Next 15.4+) |
| APIs nativas de Bun | ⚠️ Limitado | import { S3Client } from "bun" no funciona con Turbopack (fix mergeado en PR #77616) |
| Streaming responses | ⚠️ Problemas | ”ReadableStream is locked” en Next 16 + Bun 1.3.2 |
La realidad: Bun como package manager para Next.js funciona excelente. Bun como runtime todavía tiene edge cases problemáticos. La documentación oficial de Bun ahora incluye guías para App Router, pero en producción muchos desarrolladores reportan que Node.js sigue siendo más estable.
Recomendación: Usa bun install y bun run build, pero considera node para el servidor de producción si encuentras issues.
Real-time y Colas
Socket.IO
| Setup | ¿Funciona? | Detalle |
|---|---|---|
| Directo | ⚠️ Limitado | Requiere configuración especial |
Con @socket.io/bun-engine | ✅ Sí | Engine nativo de Bun desarrollado por el equipo de Socket.IO |
Nota: A menos que necesites fallback a polling, considera usar WebSockets nativos de Bun directamente—son significativamente más rápidos.
BullMQ
| Métrica | Resultado |
|---|---|
| ¿Funciona? | ⚠️ Parcial |
| Performance boost | Solo ~20% (bottleneck en IORedis) |
| Bun.redis | No soportado aún |
Auth y Pagos
bcrypt (nativo)
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Original | ❌ No | Addon nativo incompatible, segfaults reportados |
| Alternativas | ✅ Sí | Usa Bun.password (nativo) o bcryptjs |
Bun tiene hashing de passwords integrado:
const hash = await Bun.password.hash("mi-password");
const valid = await Bun.password.verify("mi-password", hash);
Stripe
| Versión Bun | ¿Funciona? | Detalle |
|---|---|---|
| 1.1.4 | ✅ Sí | Funciona correctamente |
| 1.1.5 | ❌ No | Regresión que rompió Stripe |
| 1.1.6+ | ⚠️ Variable | Verifica con tu versión |
Las regresiones son un problema real. Un upgrade de Bun puede romper integraciones críticas.
Cloud y AWS
AWS SDK v3
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Servicios básicos | ✅ Sí | S3, DynamoDB, etc. funcionan |
| S3 con SDK | ✅ Sí | 5x más rápido que en Node.js desde Bun 1.1.25 |
| Bun.s3 nativo | ✅ Recomendado | 5x más rápido que @aws-sdk/client-s3 |
Si solo necesitas S3, considera usar Bun.s3 directamente en lugar del SDK.
ORMs y Bases de Datos
Prisma
| Operación | ¿Funciona? | Detalle |
|---|---|---|
| Queries | ✅ Sí | El cliente funciona |
prisma generate | ⚠️ Requiere Node.js | El CLI se cuelga si Node no está instalado |
prisma migrate | ⚠️ Requiere Node.js | Mismo problema |
| Docker | ⚠️ Problemático | Errores de Query Engine por arquitecturas incompatibles |
El equipo de Prisma está trabajando en un nuevo generador “Rust-free” que mejora la situación, pero hoy necesitas Node.js instalado aunque ejecutes tu app con Bun.
TypeORM
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Decorators básicos | ✅ Sí | Desde Bun 1.0.3 con emitDecoratorMetadata |
| Casos edge | ⚠️ Problemático | Reportes de Cannot find module con metadata internos |
Drizzle ORM
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Todo | ✅ Sí | Soporte nativo, integración con Bun.sql |
Veredicto: Usa Drizzle si empiezas un proyecto nuevo. Si ya tienes Prisma, mantén Node.js en tu toolchain.
Mongoose
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Conexión básica | ✅ Sí | MongoDB driver funciona |
| Todas las features | ✅ Sí | Documentación oficial de Bun confirma compatibilidad |
Browser Automation
Puppeteer
| Plataforma | ¿Funciona? | Detalle |
|---|---|---|
| Linux | ✅ Sí | Funciona desde Bun 1.1 |
| macOS | ✅ Sí | Funciona desde Bun 1.1 |
| Windows | ⚠️ Inestable | Comportamiento impredecible, exits aleatorios |
Playwright
| Plataforma | ¿Funciona? | Detalle |
|---|---|---|
| Linux | ✅ Sí | Funciona desde Bun 1.1 |
| macOS | ✅ Sí | Funciona desde Bun 1.1 |
| Windows | ⚠️ Parcial | Named pipes implementados en v1.1.29+, pero aún hay reportes de timeouts |
Veredicto: Si desarrollas en Windows o tu CI corre en Windows, quédate con Node.js.
Procesamiento de Imágenes
Sharp
| Operación | ¿Funciona? | Detalle |
|---|---|---|
| Runtime | ✅ Sí | Funciona una vez instalado |
bun install | ❌ No | Postinstall scripts no compatibles |
| Segfaults | ⚠️ Reportados | En Docker y operaciones concurrentes |
Workaround: Instala con npm install sharp y luego usa bun para ejecutar.
node-canvas
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Original | ❌ No | Usa node-gyp que requiere compilación nativa |
| @napi-rs/canvas | ⚠️ Con issues | Problemas con musl/glibc, crashes en executables |
Nota: @napi-rs/canvas no requiere node-gyp, pero tiene sus propios issues con Bun. Verifica la compatibilidad con tu versión.
Bots y Gaming
Discord.js
| Feature | ¿Funciona? | Detalle |
|---|---|---|
| Texto/comandos | ✅ Sí | Funciona correctamente |
| Voice channels | ❌ No | @discordjs/voice falla porque @discordjs/opus (nativo) no carga correctamente y hay problemas de conexión |
Veredicto: Si solo necesitas un bot de texto, adelante. Si necesitas audio, quédate con Node.js.
El elefante en la sala
Mirando la lista anterior, surge una pregunta obvia: ¿Por qué Bun construye clientes nativos de S3, Postgres y Redis antes de completar la compatibilidad con Node.js?
La respuesta oficial del equipo de Bun en su documentación de Bun.sql:
“Creemos que es más simple para los desarrolladores tener un driver de base de datos integrado en Bun. El tiempo que pasas eligiendo librerías es tiempo que podrías estar construyendo tu app.”
Y hay una razón técnica:
“Aprovechamos algunos internals del motor JavaScriptCore para hacer más rápida la creación de objetos de formas que serían difíciles de implementar en una librería.”
En otras palabras: estas features nativas son significativamente más rápidas que sus equivalentes en npm precisamente porque están integradas en el runtime.
Pero esto crea una tensión. Cada hora de ingeniería dedicada a Bun.redis es una hora no dedicada a arreglar node:cluster en macOS. Es una decisión de producto legítima, pero debes entender las implicaciones:
Bun está apostando a que prefieres features nuevas y rápidas sobre compatibilidad perfecta con el ecosistema existente.
Si tu prioridad es migrar un proyecto Node.js existente sin sorpresas, esa apuesta puede no alinearse con tus necesidades.
Los fantasmas en producción
Más allá de la compatibilidad de APIs, hay problemas de estabilidad que debes conocer.
Segfaults bajo carga
En diciembre de 2024, un desarrollador reportó crashes aleatorios en producción:
“Segfaults aleatorios pasando docenas de veces al día, correlacionando aproximadamente con períodos de mayor carga.”
El problema desapareció al volver a Bun 1.1.33 desde 1.1.38. Docker reiniciaba el container automáticamente, pero el problema persistía hasta el rollback.
Regresiones que rompen paquetes
El caso de Stripe es ilustrativo. La versión 1.1.5 de Bun rompió la integración con Stripe. La solución fue hacer downgrade a 1.1.4.
Esto significa que no puedes asumir que un upgrade de Bun es seguro. Necesitas un pipeline de CI que pruebe tus integraciones críticas antes de actualizar.
El problema de Windows
Múltiples paquetes (Playwright, Puppeteer, y otros) tienen problemas específicos en Windows que no existen en Linux o macOS. Si tu equipo desarrolla en Windows o tu CI corre en Windows, vas a encontrar más fricción.
Veredicto: ¿Deberías hacer el switch?
Después de toda esta investigación, aquí está mi framework de decisión:
Usa Bun si…
- ✅ Construyes CLIs o herramientas de desarrollo (el single-binary es genial para distribución)
- ✅ Desarrollas APIs simples con Hono o Elysia (frameworks diseñados para Bun)
- ✅ Tu stack es Express básico sin dependencias nativas complejas
- ✅ Necesitas SQLite, Postgres o S3 y quieres máxima performance
- ✅ Es un proyecto nuevo donde puedes elegir dependencias Bun-friendly
- ✅ Desarrollas en Linux o macOS (Windows tiene más issues)
No uses Bun si…
- ❌ Haces trabajo criptográfico intensivo (10-14x más lento que Node.js)
- ❌ Tu CI o equipo desarrolla en Windows (Playwright, Puppeteer, y otros tienen issues)
- ❌ Necesitas compatibilidad perfecta con un codebase Node.js existente grande
- ❌ Usas native addons como node-canvas, bcrypt nativo, sharp (sin workarounds)
- ❌ Dependes de Discord.js con audio
Evalúa cuidadosamente si…
- ⚠️ Usas Next.js — funciona como package manager, pero el runtime tiene edge cases (streaming, meta tags, hot reload)
- ⚠️ Usas NestJS — oficialmente “compatible” pero sin soporte del equipo de NestJS
- ⚠️ Dependes de Prisma — el cliente funciona pero el CLI requiere Node.js instalado
Checklist de auditoría pre-migración
Antes de intentar migrar, responde estas preguntas:
1. ¿Usas módulos nativos?
Ejecuta este comando para identificarlos:
npm ls | grep -E "(native|binding|addon)"
Según la documentación de Bun sobre módulos, los addons N-API deberían funcionar, pero los que dependen de node-gyp pueden fallar.
N-API (Node-API) es la interfaz estable de Node.js para crear extensiones nativas en C/C++. A diferencia de las APIs internas de V8 que cambian entre versiones, N-API garantiza compatibilidad binaria—un addon compilado para Node 14 funciona en Node 20 sin recompilar. Bun reimplementa esta API para que los addons existentes funcionen sin modificaciones.
Alternativas comunes:
| Paquete nativo | Alternativa Bun-friendly |
|---|---|
bcrypt | bcryptjs o Bun.password |
node-canvas | @napi-rs/canvas (con limitaciones) |
better-sqlite3 | bun:sqlite nativo |
2. ¿Tu proyecto tiene >50k líneas de código?
Un desarrollador documentó la migración de un monorepo con 300+ paquetes y ~100,000 líneas. Sus conclusiones:
“Terminé removiendo la mayoría de referencias a
Bun.*y asegurando que donde uso el globalbun, lo importe así:import Bun from 'bun'. De esta forma todo puede correr en Node también.”
La recomendación: mantén compatibilidad dual hasta estar seguro de que todo funciona.
3. ¿Desarrollas o deployeas en Windows?
Bun 1.1 agregó soporte oficial para Windows, pero con limitaciones:
- Solo soporta x64, no ARM
- Playwright y Puppeteer tienen comportamiento impredecible
- Algunos usuarios reportan segfaults en instalación
Considera usar WSL o contenedores Linux para desarrollo si tu equipo está en Windows.
4. ¿Tus tests cubren integraciones críticas?
Antes de migrar, ejecuta tu suite de tests con Bun:
bun test
Como vimos con el caso de Stripe, las regresiones son reales. La guía de migración a producción recomienda:
“Monitorea las tasas de error obsesivamente las primeras 48 horas. Si algo se rompe, un comando revierte el deployment.”
5. ¿Puedes hacer rollback rápido?
Bun convierte automáticamente package-lock.json a bun.lock, preservando las versiones resueltas. Pero mantén tu lockfile original:
# Guarda el lockfile original
cp package-lock.json package-lock.json.backup
# Migra a Bun
bun install
# Si algo falla, rollback inmediato
mv package-lock.json.backup package-lock.json
rm bun.lock
npm install
6. ¿Tus dependencias tienen postinstall scripts?
A diferencia de npm, Bun no ejecuta lifecycle scripts por defecto por seguridad. Solo los paquetes en el top 500 de npm están en la allowlist.
Para ver qué scripts fueron bloqueados:
bun pm untrusted
Para confiar en un paquete específico:
bun pm trust <nombre-paquete>
O agrégalo a tu package.json:
{
"trustedDependencies": ["sharp", "puppeteer", "@prisma/client"]
}
Después de agregar, reinstala:
rm -rf node_modules
rm bun.lock
bun install
Conclusión
Bun es un proyecto impresionante con una visión clara: hacer JavaScript más rápido y simple. Pero esa visión no es ser una copia de Node.js.
La pregunta “¿Puedo reemplazar Node.js con Bun?” tiene una respuesta honesta: depende de tu stack específico. Para algunos proyectos, Bun es estrictamente mejor. Para otros, es un downgrade funcional.
Lo más importante que debes recordar:
- El objetivo es 90% de compatibilidad, no 100%
- Las features nuevas (S3, Redis, Postgres) compiten por recursos con la compatibilidad
- Windows tiene más problemas que Linux/macOS
- Las regresiones entre versiones son reales—no asumas que upgrades son seguros
- Audita tu stack antes de migrar
Bun no prometió reemplazar Node.js al 100%. Y ahora sabes exactamente qué significa eso para tu proyecto.