Cada tanto, en un standup o en un hilo de Slack, alguien lo dice en voz alta: «¿en serio hacen falta tres runtimes de JavaScript? ¿no bastaba con Node?». Es una pregunta honesta. Desde afuera parece fragmentación gratuita — el tipo de cosa que en frontend nos costó años de fatiga de frameworks.
Pero cuando entiendes de dónde sale cada uno, la historia deja de parecer un capricho. Los tres no compiten por exactamente lo mismo: son tres respuestas a tres momentos distintos del lenguaje.

node (2009): el pionero, con sus deudas
Node lo armó Ryan Dahl en 2009 pegando el motor V8 de Chrome a una capa de I/O no bloqueante. La idea era poderosa y, en retrospectiva, obvia: usar JavaScript fuera del navegador, en el servidor, con un modelo de eventos en lugar de un hilo por request. Funcionó. Node se comió el backend y hoy sostiene una parte enorme de la web.
Pero llegó primero, y llegar primero se paga. Node cargó con decisiones que en 2009 eran razonables y hoy son deudas de diseño:
- CommonJS (
require) antes de que existieran los ES Modules. Vivimos años con dos sistemas de módulos incompatibles conviviendo a la fuerza. node_modules, esa carpeta que pesa más que tu sistema operativo y que se volvió meme por derecho propio.- Cero TypeScript. Para correr TS necesitabas un transpilador, un paso de build y su configuración.
- Ningún modelo de seguridad. Cualquier paquete que instalas — y sus cientos de dependencias transitivas — puede leer tu disco, tus variables de entorno o abrir sockets.
npm installes, en la práctica, ejecutar código de extraños con tus permisos.
Ninguna de esas cosas era un error en su momento. Son cicatrices de haber inventado la categoría.
deno (2018): la corrección filosófica
Lo interesante es quién señaló esas deudas primero: el propio Ryan Dahl. En 2018 dio una charla titulada «10 Things I Regret About Node.js» donde enumeró, una por una, las cosas que habría hecho distinto. Y en vez de quedarse en el lamento, construyó la alternativa: Deno, escrito en Rust sobre V8.
Deno es Node reescrito con la lección aprendida, y sus apuestas son exactamente las correcciones a las deudas de arriba:
- Seguridad por permisos explícitos. Un script no puede tocar el disco, la red ni el entorno salvo que lo arranques con
--allow-read,--allow-nety compañía. El default es no confiar. - TypeScript nativo, sin configuración ni paso de build.
- ES Modules desde el día uno.
- APIs alineadas con los estándares web:
fetch,Request,Response,URL. Lo que ya sabes del navegador funciona igual en el servidor.
Por años, el costo de esa pureza fue la incompatibilidad con npm. Eso cambió: Deno 2, en octubre de 2024, hizo las paces con el ecosistema — reconoce package.json y node_modules, importa paquetes con el prefijo npm: y trae deno install. La corrección filosófica se volvió pragmática sin renunciar a sus principios.
bun (2022): la optimización pragmática
Bun, que Jarred Sumner presentó en 2022 y llevó a su versión 1.0 en septiembre de 2023, juega otro juego. No quiere corregir la filosofía de Node — quiere ser un Node más rápido y con menos piezas.
Donde Node y Deno usan V8, Bun usa JavaScriptCore, el motor de Safari, y está escrito en Zig (con el dato fresco de que en 2026 el equipo arrancó una reescritura a Rust, todavía en curso). Pero su verdadera apuesta es el «todo en uno»: runtime, gestor de paquetes, bundler y test runner en un solo binario. Donde un proyecto Node típico junta node + npm + esbuild + jest, Bun te da todo eso con un comando. Y bun install es absurdamente rápido.
En diciembre de 2025 Bun fue adquirido por Anthropic, que lo mantiene open source, con licencia MIT y el mismo equipo. Lo apunto porque cambia el cálculo de riesgo: un proyecto que parecía la apuesta de una sola persona ahora tiene respaldo serio detrás.
Si tuviera que resumir los tres en una frase: Node es el incumbente, Deno es la corrección filosófica, Bun es la optimización pragmática.

entonces, ¿cuál uso?
Node para producción seria. Es el default que nadie te va a cuestionar en un code review. La compatibilidad está garantizada, la respuesta de StackOverflow a cualquier problema ya existe, y tu proveedor de hosting lo soporta sin que tengas que pensarlo. Si el proyecto importa y duerme en producción, Node sigue siendo la respuesta aburrida y correcta.
Deno cuando la seguridad es parte del problema — correr código de terceros, scripts que no quieres que toquen tu disco, entornos multi-tenant —, cuando quieres TypeScript sin pelear con tsconfig, o cuando valoras un ecosistema curado y orientado a estándares.
Bun por velocidad en desarrollo. Y aquí va el patrón que más se repite: Bun como herramienta de desarrollo, Node en producción. bun install y bun test en tu máquina y en CI porque son rápidos; el contenedor que va a producción corre sobre Node porque es lo probado. Es un híbrido perfectamente válido y bastante común. No tienes que casarte con un solo runtime para todo el ciclo de vida.

no es fragmentación, es la guerra de los navegadores otra vez
Aquí está mi opinión de fondo: lo que desde afuera parece un desperdicio de esfuerzo es, en realidad, lo mejor que le pudo pasar al ecosistema. Y ya lo vivimos una vez.
¿Te acuerdas de cuando Internet Explorer tenía el 95% del mercado? La web se estancó. IE6 reinó años sin competencia real, y sin presión no había razón para mejorar. Lo que destrabó todo fue Firefox primero y Chrome después: de pronto había con quién compararse, y los navegadores se vieron obligados a correr.
Con los runtimes pasó lo mismo. Node pasó años cómodo, sin nadie pisándole los talones, moviéndose despacio. Y mira lo que agregó desde que Deno y Bun existen:
- un test runner nativo (
node:test), estable desde Node 20 — justo lo que Bun vendía como ventaja; - la bandera
--env-filedesde Node 20.6, para cargar archivos.envsin la dependenciadotenv; - soporte de TypeScript integrado: experimental con bandera en Node 22, sin bandera en Node 23 y activado por defecto en Node 24, la LTS actual. El runtime borra las anotaciones de tipo y corre el
.tsdirecto (con límites: losenumy los namespaces con código en runtime todavía piden opt-in); - un
fetchglobal estable desde Node 21, alineado con el mismo estándar web que Deno empujó.
No es casualidad. Es competencia funcionando como debe: cada feature que Deno o Bun presumieron como diferenciador terminó empujando a Node a moverse. El incumbente dejó de dormirse porque ahora hay con quién compararlo.
el dato que tranquiliza: WinterTC
Falta la pregunta de fondo: ¿no me estoy arriesgando a escribir código que solo corra en un runtime y quedar atrapada?
Cada vez menos, y por una razón concreta: WinterTC (antes WinterCG). Es el comité — desde diciembre de 2024, el TC55 de Ecma International, la misma casa que estandariza el lenguaje a través del TC39 — donde Node, Deno, Cloudflare Workers y compañía se sientan a acordar un conjunto común de APIs. Su trabajo central es la minimum common API: el subconjunto de la plataforma web (fetch, Request, Response, URL, streams, crypto…) que todos los runtimes interoperables se comprometen a soportar igual. El objetivo declarado es que el código portable sea la norma, no la excepción.

Traducido: la decisión de runtime cada vez te ata menos. Si escribes contra las APIs estándar, mover un servicio de Node a Bun o a Deno se parece más a cambiar de intérprete que a reescribir.
Y aun en el peor caso, hay que poner el riesgo en perspectiva. El costo de equivocarte de runtime es bajísimo comparado con equivocarte de framework de frontend. Cambiar de Node a Bun es, casi siempre, ajustar comandos de build y tocar un Dockerfile. Migrar de un framework de frontend a otro es reescribir la aplicación. Una decisión es reversible en una tarde; la otra te marca por años.
lo que de verdad debería preocuparnos
Así que no: tres runtimes no me parecen una locura. Me parecen salud.
Lo que sí me preocuparía es lo contrario — un solo runtime, sin nadie enfrente, marcando el ritmo del ecosistema entero a su antojo. Eso ya lo vivimos: se llamaba IE6, y nos costó casi una década salir de ahí. Tener a Node, Deno y Bun corriendo, copiándose las buenas ideas y rindiéndole cuentas a un estándar común, no es el problema.
Es exactamente el seguro que querríamos tener.