Arquitectura · 28 de octubre de 2026 · Daniel Murillo
Node.js vs Bun vs Deno en 2026: una decisión de arquitectura
El mejor runtime es el que cumple tus requisitos con el equilibrio correcto de rendimiento, compatibilidad, seguridad y costo operativo.
El mejor runtime es el que cumple los requisitos de tu aplicación con el equilibrio correcto de rendimiento, compatibilidad, seguridad, complejidad y costo operativo.
Introducción: tres runtimes, distintas prioridades
Node.js, Bun y Deno ejecutan JavaScript, pero no persiguen exactamente la misma propuesta.
- Node.js apuesta por un ecosistema amplio, compatibilidad y una plataforma operativa madura.
- Bun combina un runtime basado en JavaScriptCore con herramientas integradas y busca un alto rendimiento en múltiples escenarios.
- Deno pone énfasis en permisos explícitos, estándares web y herramientas integradas, mientras amplía la compatibilidad con Node y npm.
La comparación se vuelve confusa cuando se pregunta simplemente cuál es «el mejor». Un runtime puede ser excelente para scripts y CLIs, otro puede reducir el riesgo de una plataforma empresarial, y otro puede encajar mejor cuando los permisos y las APIs web son prioridades.
La decisión no debería ser un concurso de popularidad ni una tabla ordenada por requests por segundo. Debe partir de la carga, las dependencias y las capacidades operativas que el proyecto necesita.
1. Resumen ejecutivo
| Dimensión | Node.js | Bun | Deno |
|---|---|---|---|
| Motor | V8 | JavaScriptCore | V8 |
| Prioridad | Compatibilidad y ecosistema | Rendimiento y herramientas integradas | Seguridad, estándares web y tooling |
| TypeScript | Soporte integrado para sintaxis común en versiones recientes; type-check separado | Ejecución/transpilación integrada; type-check separado | Ejecución y deno check integrados |
| Paquetes | npm, pnpm, Yarn | bun install y paquetes npm | npm, JSR y lockfiles de varios gestores |
| APIs de Node | Referencia principal | Compatibilidad amplia, no total | Compatibilidad creciente, no total |
| Permisos de I/O | Normalmente según el usuario del proceso y el sistema operativo | No es el diferenciador central | Permisos explícitos para archivos, red, entorno y procesos |
| Frameworks representativos | Express, Fastify, NestJS, AdonisJS, Hono | Elysia, Hono; también muchas apps Node compatibles | Hono, Fresh, Oak; muchas dependencias npm con validación |
| Fortaleza típica | Dependencias maduras y operación conocida | Arranque, tooling y ciertos workloads de rendimiento | Modelo de permisos y experiencia integrada |
| Principal cautela | Tooling fragmentado y necesidad de gobernar dependencias | Diferencias de compatibilidad y observabilidad | Compatibilidad concreta de dependencias y permisos operativos |
La tabla es una guía inicial, no una clasificación absoluta. Las capacidades evolucionan con cada versión.
2. No mezclemos las capas
Para comparar con rigor, hay que separar cuatro capas:
- Motor JavaScript: V8 o JavaScriptCore.
- Runtime: APIs de red, archivos, procesos, módulos, timers y herramientas del sistema.
- Framework: routing, middleware, validación, inyección de dependencias y convenciones.
- Aplicación: lógica de negocio, consultas a base de datos, autenticación, caché, logging y llamadas a terceros.
Un benchmark de Bun.serve() no es una comparación justa contra una aplicación NestJS. Tampoco una prueba de Express con TLS permite concluir cuál runtime será mejor en un servicio que pasa la mayor parte del tiempo esperando PostgreSQL.
La comparación debe indicar qué capa está midiendo.
3. Benchmarks publicados: evidencia útil, no sentencia final
Los benchmarks de los proyectos permiten identificar hipótesis. No deben mezclarse como si todos provinieran de una misma máquina y metodología.
Express sobre HTTPS
Bun publica una prueba de Express 5.2.1 con TLS 1.3, bombardier, Linux x64 y AMD EPYC. Los datos son medianas de tres ejecuciones:
| Runtime | Versión | Requests/s | RAM máxima |
|---|---|---|---|
| Bun | 1.4 | 48 243 | 105 MB |
| Node.js | 26.7.0 | 25 181 | 142 MB |
| Deno | 2.9.5 | 19 243 | 176 MB |
En esta prueba, Bun logra cerca de 1,9× el throughput de Node y 2,5× el de Deno. Eso es relevante para investigar el comportamiento de Express sobre esos runtimes, pero no prueba que cualquier API de negocio vaya a mejorar en la misma proporción.
Fuente: Bun — benchmarks
PostgreSQL: cuidado con comparar drivers diferentes
La misma página compara una carga de PostgreSQL con 100 filas por consulta, 100 consultas en vuelo y 100 000 consultas totales. Bun utiliza su API SQL integrada, mientras Node y Deno usan postgres.js 3.4.9.
| Runtime / driver | Consultas/s | RAM máxima |
|---|---|---|
Bun 1.4 (Bun.sql) | 20 243 | 80 MB |
Deno 2.9.5 (postgres.js) | 10 406 | 181 MB |
Node.js 26.7.0 (postgres.js) | 10 000 | 168 MB |
No es una comparación pura del runtime. Cambia también el cliente de base de datos, por lo que el resultado representa el conjunto de implementación y configuración. Para una comparación controlada, usa el mismo driver si está disponible y verifica que cada versión haga exactamente el mismo trabajo.
Fuente: Bun — benchmarks
Deno 2.9 frente a Deno 2.8
Deno reportó estas mejoras en su servidor Deno.serve, con concurrencia 100, en una máquina Linux x86_64 dedicada:
| Métrica | Deno 2.8 | Deno 2.9 |
|---|---|---|
| Cold start | 34,2 ms | 17,3 ms |
| HTTP realworld | 56,8k req/s | 72,4k req/s |
| HTTP texto | 77,0k req/s | 85,6k req/s |
| Respuesta de 1 MiB | 1 617 req/s | 1 907 req/s |
| RSS, realworld | 142 MB | 64 MB |
Es una mejora entre versiones de Deno, no una comparación directa con Bun o Node. La carga «realworld» del benchmark recibe JSON con un bearer token y lo devuelve como JSON, pero sigue siendo una aplicación simplificada.
Fuente: Deno 2.9 — performance
Streams: optimizar una API concreta importa
Bun 1.4 publicó una prueba de Response.clone() con un cuerpo de 64 MB. En la configuración descrita por el proyecto, Bun reporta 220 MB de pico de memoria y 96 ms, Node.js 26 reporta 382 MB y 230 ms, y Deno 2.9 reporta 297 MB y 134 ms.
El artículo de Bun explica que una optimización evita copiar el cuerpo completo en la segunda rama. Es una ventaja importante para esa operación, no evidencia de que toda manipulación de streams sea siempre más rápida.
Fuente: Bun 1.4 — performance
¿Qué conclusión se puede extraer?
- Bun muestra ventajas importantes en varios escenarios publicados por su equipo.
- Deno 2.9 mejoró de forma considerable frente a Deno 2.8 en las pruebas que publicó.
- Node.js sigue siendo una opción competitiva, pero su ventaja más amplia suele estar en el ecosistema y la compatibilidad, no en ganar cada microbenchmark.
- No se puede construir un ranking universal mezclando tablas con diferentes cargas.
- Una aplicación real debe medirse con sus dependencias, configuración, límites y SLO.
4. ¿Qué runtime elegir según el proyecto?
Plataforma empresarial con muchas dependencias
Primera opción a evaluar: Node.js.
Es especialmente razonable cuando la aplicación depende de SDKs cloud, módulos nativos, drivers, agentes APM y librerías cuyo soporte principal es Node. El valor está en reducir incertidumbre, facilitar diagnóstico y aprovechar la experiencia del equipo.
Bun y Deno siguen siendo opciones posibles, pero habría que validar cada integración crítica y comparar el costo de mantener las diferencias.
API nueva en TypeScript
Evaluaría los tres.
- Node.js con Fastify o NestJS ofrece una base madura.
- Bun con
Bun.serve()o Elysia puede ser atractivo si el rendimiento o el tooling integrado importan. - Deno con Hono puede resultar interesante si se valoran APIs web, permisos y herramientas integradas.
La elección final depende de las dependencias, el estilo arquitectónico del equipo y los resultados de una prueba representativa.
CLI, scripts y automatización
Bun y Deno merecen especial atención.
Sus herramientas integradas pueden simplificar el desarrollo y el arranque. Deno aporta un modelo de permisos útil para scripts que no deberían tener acceso irrestricto a todo el sistema. Bun puede ser atractivo por su velocidad y su integración de gestor de paquetes, test runner y bundler.
Node sigue siendo una buena elección cuando el script depende de paquetes o APIs específicas de Node.
Servicio con requisitos de seguridad por permisos
Evaluaría Deno.
Su modelo de permisos explícitos permite limitar acceso a archivos, red, entorno y procesos. La ventaja es especialmente útil cuando esos límites forman parte del diseño. No reemplaza el aislamiento del sistema operativo, la revisión de dependencias ni los controles de despliegue.
WebSockets, streaming o alto throughput
No elijas por el nombre del runtime.
Bun publica resultados interesantes de WebSockets y streams; Deno ha mejorado su servidor HTTP; Node dispone de un ecosistema maduro. Pero las diferencias dependen del patrón de mensajes, tamaño de payload, fan-out, TLS, backpressure, serialización y confirmación de entrega.
Haz una prueba de carga con la topología real: número de conexiones, mensajes por segundo, tamaño de mensajes, percentiles de latencia, memoria y reconexiones.
5. Frameworks: elegirlos por separado del runtime
| Framework | Entorno habitual | Por qué evaluarlo |
|---|---|---|
| Express | Node.js | Ecosistema extenso y simplicidad |
| Fastify | Node.js | Validación, serialización, plugins y bajo overhead |
| NestJS | Node.js | Estructura modular, inyección de dependencias y convenciones |
| Elysia | Bun | Diseño estrechamente integrado con Bun y TypeScript |
| Hono | Node.js, Bun, Deno y otros | APIs web y portabilidad |
| Fresh | Deno | Aplicaciones web con renderizado en servidor e islas |
| Oak | Deno | Middleware framework con estilo inspirado en Koa |
Las columnas no significan que un framework no pueda ejecutarse fuera de su entorno habitual. La compatibilidad real depende de las APIs, plugins y dependencias que use el proyecto.
Si la portabilidad importa, usar estándares web y aislar APIs de runtime puede reducir el acoplamiento. Si se requiere un framework con un ecosistema muy específico, prioriza la compatibilidad y la experiencia operativa sobre una abstracción teórica.
6. Una metodología justa de benchmarking
Un benchmark útil debe contestar una pregunta concreta. Antes de ejecutar pruebas, define la hipótesis: ¿quieres reducir costo por request, mejorar p99, bajar memoria por réplica, acelerar cold starts o reducir el tiempo de CI?
Condiciones controladas
- Fija las versiones exactas de runtime, framework y dependencias.
- Usa el mismo hardware, sistema operativo y límites de contenedor.
- Ejecuta el mismo trabajo de negocio y, cuando sea posible, el mismo framework.
- Usa el mismo dataset, pool de conexiones, caché y configuración de TLS.
- Verifica que el generador de carga no sea el cuello de botella.
- Repite las ejecuciones y registra variabilidad.
- Separa arranque en frío de rendimiento sostenido.
- Documenta código y configuración para que otro equipo pueda reproducir el resultado.
Métricas
- Throughput: solicitudes completadas por segundo.
- Latencia p50, p95 y p99.
- CPU por solicitud.
- Memoria RSS y evolución del heap.
- Tiempo de arranque.
- Errores, timeouts y conexiones rechazadas.
- Estabilidad bajo carga sostenida y durante picos.
- Costo de infraestructura para cumplir el SLO.
No reportes solo requests por segundo. Un servidor puede producir más throughput a costa de una cola de latencia más larga o de un consumo de memoria que obliga a escalar más réplicas.
Tres escenarios
A. Endpoint mínimo: permite aproximarse al techo del servidor.
B. API representativa: routing, validación, autenticación, serialización y acceso a datos.
C. Simulación de producción: TLS, tracing, logs, límites de contenedor, carga sostenida y fallos de dependencias.
La prueba B o C debería pesar más en la decisión que la prueba A.
7. Costos que no aparecen en una tabla de rendimiento
Costo de compatibilidad
Una dependencia que no funciona puede costar más que una mejora de throughput. Cuenta las integraciones críticas, las APIs incompatibles, los parches y las horas de mantenimiento.
Costo operativo
Evalúa el soporte en plataformas de despliegue, imágenes base, health checks, apagado ordenado, workers, observabilidad, profiling y respuesta a incidentes.
Costo de aprendizaje
Un equipo experto en Node puede entregar más rápido con Node aunque otro runtime sea superior en un benchmark. Un equipo nuevo puede preferir el tooling integrado de Bun o Deno. El costo de aprendizaje es parte de la decisión.
Costo de infraestructura
Si un runtime reduce memoria o CPU en una carga real, podría disminuir el número de réplicas. Pero esa mejora debe mantenerse con las dependencias, logs y límites de producción. Calcula el costo por volumen de tráfico o por tarea completada, no solo la velocidad máxima.
Costo de migración
Migrar un sistema en funcionamiento implica pruebas, rollout, observabilidad, rollback y capacitación. Una mejora marginal en un endpoint no suele justificar ese costo.
8. Matriz de decisión ponderada
Puntúa cada criterio para tu proyecto del 1 al 5 y asigna un peso. No uses una puntuación universal para todos los equipos.
| Criterio | Peso inicial sugerido | Node.js | Bun | Deno |
|---|---|---|---|---|
| Compatibilidad con dependencias críticas | 5 | Suele ser la referencia | Validar APIs y módulos nativos | Validar APIs y módulos nativos |
| Rendimiento en la carga real | 5 | Medir | Medir | Medir |
| Seguridad por permisos de runtime | 4 | Requiere controles adicionales | No es su diferenciador principal | Diferenciador central |
| Tooling integrado | 3 | Ecosistema modular | Integrado | Integrado |
| Observabilidad y soporte operacional | 5 | Ecosistema muy amplio | Probar APM y profiling | Probar APM y profiling |
| Experiencia del equipo | 4 | Depende del equipo | Depende del equipo | Depende del equipo |
| Tiempo de arranque | 2–5 según el caso | Medir | Medir | Medir |
| Costo por carga atendida | 5 | Medir | Medir | Medir |
| Portabilidad entre runtimes | 2–5 según el caso | APIs de Node | Mejor si se usan estándares web | Mejor si se usan estándares web |
Los pesos son un punto de partida, no una recomendación inmutable. En una CLI, el arranque puede tener peso 5; en una API de negocio dominada por SQL, la velocidad de arranque quizá tenga poco impacto.
9. Estrategia de adopción con riesgo controlado
No es obligatorio estandarizar toda una organización en un solo runtime desde el primer día. Una estrategia razonable es:
- Mantener el runtime actual como baseline.
- Seleccionar un servicio pequeño con dependencias acotadas.
- Automatizar tests funcionales y de compatibilidad.
- Comparar rendimiento con condiciones controladas.
- Probar observabilidad, contenedores, health checks y apagado.
- Desplegar gradualmente con métricas y rollback.
- Ampliar el uso solo si los beneficios son sostenibles.
Evita terminar con tres runtimes por moda. La diversidad puede ser útil, pero añade versiones, pipelines, documentación y habilidades que mantener. Introduce una nueva plataforma cuando resuelva un problema concreto.
10. Recomendación final
Elige Node.js cuando la compatibilidad, el ecosistema y la operación conocida sean prioritarios, especialmente en sistemas grandes con muchas dependencias e integraciones.
Elige Bun cuando el tooling integrado, el arranque o el rendimiento medido en tu carga aporten un beneficio concreto y puedas validar las dependencias críticas.
Elige Deno cuando el modelo de permisos, las APIs web y el flujo de desarrollo integrado encajen con los requisitos de seguridad y arquitectura.
No hay que convertir estas tendencias en reglas absolutas. Node.js puede ser más apropiado para una API nueva; Bun puede ser una gran elección para un sistema empresarial; Deno puede ser una opción válida aunque el equipo use algunas librerías npm. Lo determinante es el ajuste entre requisitos y capacidades.
La mejor decisión no es el runtime que gana un benchmark publicado por su propio equipo. Es el que cumple los objetivos de latencia, costo, seguridad y mantenibilidad con un nivel de riesgo que el equipo puede sostener.
Mide tu aplicación. Revisa las dependencias. Decide según el problema.
En esta serie
- Node.js: por qué sigue siendo una apuesta sólida
- Bun: ¿realmente es más rápido que Node.js?
- Deno: seguridad, TypeScript y herramientas
- Comparativa final (esta nota)
Lecturas relacionadas
- Node.js vs Bun vs Deno: cómo elegir un runtime
- NestJS, Spring Boot y FastAPI
- Monorepo: Bun, pnpm y Nx
- Benchmarks y decisiones de arquitectura
- Herramienta: qué runtime te conviene
- Herramienta: qué frontend te conviene
- Herramienta: qué backend te conviene
- Herramienta: qué protocolo de API te conviene
Referencias
- Node.js — Release schedule
- Node.js — TypeScript
- Bun — Runtime
- Bun — Node.js compatibility
- Bun 1.4
- Bun benchmarks
- Deno 2.9
- Deno — Security and permissions
- Deno — Node and npm compatibility
- Hono
- Elysia
- Fastify benchmarks
Los benchmarks se atribuyen a los proyectos que los publican. Los resultados no forman una clasificación independiente y universal: varían por versión, carga, hardware, framework, driver y configuración. Antes de tomar una decisión de producción, reproduce las pruebas relevantes y añade una prueba representativa de tu aplicación.