Deno 2.0 salió en octubre de 2024 y, cinco meses después, es un buen momento para hacer balance. La versión 2.0 no se parece al Deno original de 2018, que nació como un rechazo explícito a muchas decisiones de Node.js. Lo que ha hecho Ryan Dahl y su equipo es, probablemente, el movimiento más pragmático que podrían hacer: aceptar que npm ganó, integrarse con el ecosistema existente, y dejar de pelearse contra package.json y node_modules. Sin perder, eso sí, las piezas que siempre han hecho a Deno distinto.
Este post es una lectura personal sobre qué ha supuesto 2.0 en proyectos reales, qué problemas resuelve, dónde sigue siendo insuficiente, y a quién le merece la pena mirarlo hoy.
Qué trae 2.0 de verdad
La noticia grande es la compatibilidad con Node. Deno 2 soporta el protocolo npm: para resolver paquetes, pero además ahora entiende package.json, respeta las dependencias declaradas ahí, crea y lee node_modules, y funciona con pnpm como gestor si está instalado. Un deno install en un proyecto existente de Node funciona. Un deno run script.js sobre un archivo que usa require('express') funciona. Esto hace un año era impensable; hoy es la base.
La segunda pieza es workspaces. Deno 2.0 soporta nativamente monorepos con múltiples paquetes, compartiendo configuración y dependencias. Para equipos con estructura de monorepo, esto era imprescindible y su ausencia en 1.x era una barrera real.
La tercera es JSR, el registro oficial que Deno, TypeScript y varios actores han empezado a empujar como alternativa moderna a npm. JSR acepta paquetes directamente en TypeScript, resuelve tipos automáticamente, publica ESM por defecto y soporta versionado semántico estricto. Es una propuesta atractiva técnicamente, pero su adopción es todavía pequeña; para la mayoría de proyectos, npm sigue siendo la fuente.
La cuarta es la compatibilidad con el Node permissions model y algunas APIs que faltaban: process.env, partes de fs, y un mejor soporte de workers. Las lagunas conocidas se han cerrado casi todas.
Qué problema resuelve en la práctica
El problema que resuelve Deno 2 es concreto: la barrera para probar Deno en un proyecto existente era demasiado alta. Antes, para migrar una app Express a Deno había que reescribir las importaciones, gestionar tipos a mano, convivir con dependencias transitivas extrañas. Hoy el experimento es abrir un proyecto existente, ejecutar deno run main.ts y ver qué pasa. En los proyectos que he probado, funciona lejos de la perfección pero lo bastante para ser útil.
Esto cambia la conversación. Deno 1.x era una apuesta de todo-o-nada: o rehacías el proyecto a su estilo, o te quedabas en Node. Deno 2.0 es una actualización gradual posible: puedes usar Deno para ejecutar, testear, analizar estilo y formatear tu proyecto Node, manteniendo package.json como fuente de verdad, y migrar a las APIs propias de Deno solo cuando te convengan. Es mucho más amistoso con la realidad de equipos que no van a reescribir su stack.
Dónde brilla todavía
Las piezas en las que Deno sigue siendo claramente mejor que Node merecen recordarse, porque son la razón para considerarlo más allá de la curiosidad.
El modelo de permisos es la más evidente. Deno ejecuta código en un entorno aislado por defecto: un script no puede leer archivos, abrir sockets, ni ejecutar subcomandos a menos que se lo permitas explícitamente con flags (--allow-read, --allow-net, etc.). Para ejecutar código de terceros (scripts de migración, herramientas de terceros, generadores) esto es un valor real. En Node, el módulo --experimental-permission avanza pero sigue siendo experimental y menos completo.
La experiencia de desarrollo sigue siendo un punto fuerte. deno fmt, deno lint, deno test, deno bench y deno task vienen integrados, con salida consistente, sin configuración, y suelen funcionar bien a la primera. En Node equivalentes requieren ensamblar prettier, eslint, vitest o jest, y tsx o ts-node para ejecutar TypeScript. Para un proyecto pequeño, la diferencia de tiempo de arranque es notable.
La nitidez de las Web APIs estándar sigue siendo elegante. fetch, Request, Response, URL, crypto.subtle, WebSocket y otras funcionan como en el navegador. Para escribir código que corre tanto en servidor como en edge (Cloudflare Workers, Deno Deploy, Bun), esto es una ventaja real. En Node 22 la convergencia ha avanzado, pero siguen existiendo diferencias sutiles que te muerden cuando portas código.
TypeScript nativo sigue siendo mejor que cualquier alternativa. Deno ejecuta TypeScript sin compilación previa, sin tsc, sin tsx, sin configuración. El rendimiento es adecuado para desarrollo e, incluso, para producción en servicios pequeños. Para equipos que escriben TypeScript en backend, ahorra capas de tooling que en Node se acumulan.
Dónde sigue cojeando
La compatibilidad con Node es mejor que nunca pero no es total. Algunos paquetes populares siguen sin funcionar. Los casos típicos son paquetes con binarios nativos que esperan exactamente la estructura de node_modules y el cargador de Node (sharp funciona bien ahora, pero fue un camino; paquetes menos mantenidos pueden fallar). Puppeteer y Playwright funcionan pero con asteriscos.
Algunos frameworks esperan un ciclo de vida de proceso específico (Next.js, NestJS) y, aunque Deno 2.0 hace un esfuerzo enorme por imitarlo, la compatibilidad con frameworks grandes sigue siendo imperfecta. Para APIs con Express, Fastify o Hono funciona bien en casi todos los casos que he visto. Para un Next.js 14 complejo, yo seguiría en Node.
La comunidad y el ecosistema son menores. La cantidad de paquetes nativos (publicados en JSR con soporte Deno-first) es pequeña todavía, y encontrar tutoriales, respuestas en Stack Overflow o ejemplos específicos de Deno es más difícil que para Node. Esto se va cerrando pero es un coste real.
El rendimiento en cold starts de scripts pequeños ha mejorado mucho, pero sigue siendo ligeramente inferior a Bun en los benchmarks que he hecho. Para servicios grandes con mucho tráfico esto no importa, pero si eres sensible a arranque rápido (funciones serverless, scripts CI muy usados), conviene medir.
Deno frente a Bun frente a Node
Como la conversación inevitablemente va a derivar aquí, un apunte breve. A principios de 2025 el ecosistema JavaScript tiene tres runtimes serios.
Node es la opción por defecto, maduro, estable y con todo el soporte del ecosistema. Si no tienes razón concreta para cambiar, no cambies. Su soporte nativo de test runner, fetch y permissions avanza cada versión.
Bun apuesta por velocidad bruta y un gestor de paquetes rapidísimo. Para desarrollo es muy agradable, y su compatibilidad con Node es buena. Para producción es usable ya pero con menos historial.
Deno apuesta por seguridad, experiencia de desarrollo y APIs web estándar. La compatibilidad con Node en 2.0 resuelve la principal fricción y lo hace usable en muchos más contextos.
Mi recomendación informal: nuevas APIs pequeñas o scripts de infraestructura, Deno 2. Servicios grandes con ecosistema establecido, Node. Desarrollo local con reinicio rápido, Bun. Para cualquier proyecto donde la seguridad frente a código de terceros sea importante, Deno por defecto.
Cómo pensar la decisión
La pregunta que resuelve Deno 2.0 no es “¿es mejor que Node?” sino “¿merece la pena intentarlo en mi proyecto?”. La respuesta, a diferencia de 2022, es un sí matizado para muchos casos.
Si tienes un proyecto nuevo que no dependa de un framework grande de Node, Deno es una opción seria. Si tienes un proyecto existente y quieres probar herramientas (formatter, tests, linter) con menos configuración, Deno puede convivir sin reescribir. Si tu preocupación es seguridad frente a dependencias de terceros, el modelo de permisos sigue siendo único.
Lo que no hay que esperar es una migración total que resuelva todos los problemas. Deno 2.0 es más humilde que Deno 1.x en ese sentido. Reconoce que Node es el estándar y que la vida práctica pasa por convivir con su ecosistema, pero sigue teniendo identidad propia. Esa doble postura, que en 2018 hubiera sido contradictoria, en 2025 es precisamente lo que lo hace viable. Un runtime tiene que elegir entre ser puro o ser útil, y Deno 2 ha elegido útil sin renunciar a sus principios de diseño. Es una decisión madura.