Node.js 24 LTS: guía de migración desde Node.js 22
Node.js 24 ya es Active LTS con soporte hasta abril de 2028. Guía práctica de migración desde Node 22: breaking changes reales, codemods y permission model.
Roberto Serrano
Ingeniero de Software

¿Te resulta útil? Déjame saber con un like o guárdalo para luego.
Hay una idea equivocada que se repite mucho últimamente: que Node.js 24 «acaba de salir». No es cierto. Node.js 24 entró en Active LTS en octubre de 2025 con la versión v24.11.0 y su nombre en clave es Krypton. Es decir, llevas un año pudiendo adoptarlo y todavía tiene por delante un ciclo de soporte hasta finales de abril de 2028.
Eso cambia por completo el encuadre del artículo. No vamos a hablar de una novedad recién publicada, sino de el LTS estable que deberías estar ejecutando ya en producción. Y de la migración desde Node.js 22, que es donde está el trabajo real.
Node 24 en el calendario de releases
Antes de tocar nada conviene tener claro dónde está cada versión. Node.js no se mueve por modas, se mueve por calendario, y ese calendario es el que decide cuándo tienes que actuar.
| Versión | Estado | Detalle |
|---|---|---|
| Node 24.0.0 | Current (2025-05-06) | Publicado por Rafael Gonzaga y Juan Arbol |
| Node 24.11.0 | Entrada en LTS (oct-2025) | Inicio del soporte hasta finales de abril de 2028 |
| Node 24.22.0 | Última del árbol 24 (14-oct-2026) | Versión recomendada hoy |
| Node 22 «Jod» | LTS | v22.23.3 (23-sep-2026), sigue siendo válido |
| Node 25 | EOL (31-mar-2026) | Fuera de soporte |
| Node 26 | Current (desde 05-may-2026) | La rama en desarrollo |
Un detalle importante para planificar a largo plazo: a partir de Node 27 el ciclo pasa a ser anual, así que las ventanas de migración se van a comprimir. Cuanto antes normalices el salto entre LTS, menos sufrirás cada año.
Y sí, Node 22 sigue en LTS y no tienes una urgencia por EOL. Pero migrar ahora, con margen, es infinitamente más barato que migrar cuando la rama 22 se acerque a su final.
Qué trae realmente Node.js 24
Node 24 no es un cambio de paradigma, es una acumulación de mejoras muy sólidas. Estas son las que de verdad vas a notar.
V8 13.6 y el JavaScript que ya puedes escribir
El motor V8 sube a la versión 13.6 y con él llegan varias funcionalidades del lenguaje que ya puedes usar sin transpilar:
Float16Array: arrays tipados de precisión media, útiles para cargas de datos y machine learning.- Gestión explícita de recursos con
usingyawait using, que cierran recursos de forma determinista al salir del bloque. RegExp.escape: escapa cadenas para usarlas dentro de una expresión regular sin dolores de cabeza.Error.isError: comprobación fiable de si un valor es un error, incluso entre realms.- WebAssembly Memory64 y
Atomics.pause, orientados a cargas intensivas.
// using cierra el recurso automáticamente al salir del bloque
class Conexion {
constructor(nombre) {
this.nombre = nombre;
console.log(`Abriendo ${nombre}`);
}
[Symbol.dispose]() {
console.log(`Cerrando ${this.nombre}`);
}
}
{
using db = new Conexion('postgres');
// ...trabajo con la conexión
} // aquí se llama a [Symbol.dispose]()
// RegExp.escape evita escapes manuales frágiles
const busqueda = 'a+b(c)';
const re = new RegExp(RegExp.escape(busqueda));
console.log(re.test('a+b(c)')); // true
npm 11 y Undici 7
El gestor de paquetes sube a npm 11 y el cliente HTTP interno pasa a Undici 7. Undici es el motor que hay detrás de fetch() en Node, así que cualquier mejora ahí se traduce directamente en tu código de red.
URLPattern ya es global
Hasta ahora, para trabajar con patrones de URL tenías que recurrir a dependencias o a expresiones regulares caseras. En Node 24, URLPattern es global y se puede usar directamente:
const pattern = new URLPattern({ pathname: '/blog/:slug' });
pattern.test('https://robertoserrano.pro/blog/nodejs-24'); // true
const match = pattern.exec('https://robertoserrano.pro/blog/nodejs-24');
console.log(match.pathname.groups.slug); // "nodejs-24"
Es una de esas APIs que simplifican el enrutado en servidores HTTP propios y en middlewares.
AsyncLocalStorage con AsyncContextFrame
AsyncLocalStorage pasa a usar AsyncContextFrame por defecto, lo que mejora el rendimiento y la propagación de contexto a través de operaciones asíncronas. Si haces trazabilidad, logging correlacionado o gestión de contexto por petición, esto te interesa.
Los breaking changes que te van a morder
Aquí está el motivo por el que este artículo existe. Migrar de Node 22 a Node 24 tiene cambios que rompen código, y algunos no dan la cara hasta que estás en producción.
OpenSSL 3.5 y el security level 2
Es, con diferencia, el fallo número uno tras migrar. Node 24 incluye OpenSSL 3.5 con el security level 2 activado, lo que prohíbe:
- Claves RSA, DSA y DH inferiores a 2048 bits.
- Claves ECC inferiores a 224 bits.
- Cifrados basados en RC4.
Si tu aplicación habla TLS con un servicio interno antiguo, con un certificado autofirmado de laboratorio o con un dispositivo heredado, la conexión empezará a fallar. Y lo hará con un error de handshake, no con un mensaje amable que te diga «tu clave es demasiado corta».
Antes de desplegar, audita los certificados con los que hablas.
El Permission Model ya no es experimental
Este es uno de los cambios más interesantes. El Permission Model abandona el estado experimental y el flag deja de llamarse --experimental-permission para pasar a ser --permission. Además aparece un modo de auditoría, --permission-audit, que no deniega nada: solo publica las violaciones por diagnostics_channel.
# Enforce: solo lectura de ./data y escritura en ./tmp, sin child processes
node --permission --allow-fs-read=./data --allow-fs-write=./tmp app.js
# Auditoría: NO deniega, solo publica violaciones por diagnostics_channel
node --permission-audit app.js
# Permitir explícitamente capacidades
node --permission --allow-child-process --allow-worker --allow-addons app.js
Conviene entender bien qué es y qué no es. El Permission Model es un «seat belt», un cinturón de seguridad, no un sandbox de seguridad. No te protege contra código malicioso. Sirve para limitar el daño de errores y de dependencias descuidadas, no para aislar código hostil.
Addons nativos: recompilar es obligatorio
Node 24 usa NODE_MODULE_VERSION = 137. Cualquier addon nativo compilado para Node 22 hay que recompilarlo. En algunos casos la compilación puede requerir C++20, así que no descartes que un paquete antiguo te obligue a actualizar su versión o a buscar alternativa.
Deprecaciones y eliminaciones
La lista es larga, pero estas son las que más aparecen en proyectos reales:
url.parse()queda deprecado en runtime.- Eliminado
tls.createSecurePair. SlowBufferdeprecado.test_runnerya no devuelve promesas.- Cambios en los argumentos de
child_process.spawnyexecFile. fs.existsSynccon tipos inválidos yfs.truncatecon descriptor de fichero (usaftruncate)._headersy_headersListdehttp.OutgoingMessage.- Validación estricta en
readline.
Comportamiento: fetch() más estricto
fetch() aplica ahora una conformidad más estricta, con validación de AbortSignal y errores en stream y pipe que ahora lanzan excepción. Viene de la guía de migración oficial v22 a v24, no de las notas de la v24.0.0, así que si no lo esperas te va a sorprender.
También hay cambios en Buffer y correcciones en rutas de Windows.
Plataformas y toolchain
Si compilas nativo o construyes imágenes base, ojo con esto:
- Sin binarios precompilados para Windows 32-bit (desde v23) ni Linux armv7 32-bit (desde v24).
- macOS mínimo 13.5.
- gcc mínimo 12.2, Xcode mínimo 16.1.
- MSVC eliminado: en Windows hay que usar ClangCL.
Checklist de migración
Este es el orden que recomiendo seguir. Es aburrido, pero es el que evita sorpresas en producción.
- Fija la versión objetivo: Node 24.22.0 o superior del árbol 24.
- Audita TLS: revisa que ningún servicio con el que hablas use claves por debajo de 2048 bits RSA o 224 bits ECC.
- Recompila addons nativos y verifica compatibilidad con
NODE_MODULE_VERSION 137. - Ejecuta
--permission-auditen un entorno de pruebas para descubrir qué permisos necesita realmente tu aplicación. - Revisa el uso de
fetch(),stream,pipeyAbortSignal. - Pasa los codemods oficiales (siguiente sección).
- Comprueba
child_processytest_runnersi los usas en tests. - Actualiza la imagen base y el toolchain si compilas en CI.
- Despliega primero en staging y vigila los logs de handshake TLS.
Si despliegas con PM2, revisa que la versión de Node apuntada por el proceso sea la nueva antes de recargar; tienes los detalles en Despliegue de aplicaciones Node con PM2. Y si tu CI ejecuta los tests, conviene coordinar el cambio de versión con la integración de OpenCode en GitHub Actions.
Codemods oficiales: automatiza lo aburrido
El equipo de Node.js publica codemods que reescriben tu código para los cambios más mecánicos. Se ejecutan uno a uno, no en lote:
npx codemod run @nodejs/crypto-rsa-pss-update
npx codemod run @nodejs/dirent-path-to-parent-path
npx codemod run @nodejs/fs-access-mode-constants
npx codemod run @nodejs/fs-truncate-fd-deprecation
npx codemod run @nodejs/http2-priority-signaling
npx codemod run @nodejs/process-assert-to-node-assert
npx codemod run @nodejs/tls-create-secure-pair-to-tls-socket
Ejecutarlos de uno en uno no es capricho: cada codemod toca un área distinta y quieres revisar el diff de cada cambio por separado. Con todo mezclado, un fallo de revisión se convierte en un bug en producción.
Permission Model en la práctica
Una vez tienes claro qué permisos necesita tu aplicación, el Permission Model tiene una API en runtime que permite comprobar y revocar permisos en caliente. Esto es especialmente útil para el patrón de «leer la configuración y luego cerrar el acceso»:
import fs from 'node:fs';
const config = fs.readFileSync('/etc/myapp/config.json', 'utf8');
// Revocar lectura tras inicializar (irreversible)
process.permission.drop('fs.read', '/etc/myapp');
process.permission.has('fs.read', '/etc/myapp/config.json'); // false
process.permission.drop('child'); // revoca el scope entero
Y para descubrir qué necesita tu app antes de desplegar, el modo auditoría se suscribe a canales de diagnostics_channel:
import diagnostics_channel from 'node:diagnostics_channel';
diagnostics_channel.channel('node:permission-model:fs').subscribe((msg) => {
console.log(`Denegado: ${msg.permission} en ${msg.resource}`);
});
Los canales disponibles son node:permission-model:fs, :child, :worker, :inspector, :wasi y :addon.
Errores comunes
Estos son los tropiezos que más se repiten al migrar:
- OpenSSL 3.5 rompe TLS con certificados antiguos. Es el fallo estrella. Audítalo antes, no después.
- Creer que el Permission Model es un sandbox. No lo es. Es un cinturón de seguridad contra errores, no contra atacantes.
- El Permission Model no se hereda. Ni a workers ni a child processes. Hay que conceder los permisos explícitamente en cada uno.
--env-filey--openssl-configse leen antes de inicializar el modelo, así que no quedan cubiertos por él.- El wildcard de rutas. Si el directorio existe, Node añade
/*automáticamente. Si no existe, tienes que poner el*a mano. - Olvidar recompilar los addons nativos. Un binario compilado para Node 22 no carga en Node 24.
Conclusión
Node.js 24 no es una novedad que haya que evaluar con cautela: es el Active LTS maduro que lleva disponible desde octubre de 2025 y que te da soporte hasta abril de 2028. Node 22 sigue siendo válido, pero cada mes que pasa sin migrar es deuda técnica que acumulas.
Los tres riesgos reales son concretos y conocidos: OpenSSL 3.5 con security level 2, el Permission Model que cambia de flag y de semántica, y los addons nativos que hay que recompilar. Todo lo demás se automatiza con los codemods oficiales y una checklist bien hecha.
Mi recomendación: planifica la migración ahora, ejecuta la auditoría de permisos en staging y sube a producción con margen. Cuando llegue la urgencia, ya será tarde para hacerlo con calma.
Si trabajas con criptografía en tus aplicaciones Node, te interesará también el módulo crypto de Node.js, donde cubro las bases que aquí se ven afectadas por el cambio de OpenSSL.
Artículos relacionados
- Cómo integrar OpenCode con GitHub Actions
- Despliegue de aplicaciones Node con PM2
- El módulo crypto de Node.js
Artículo escrito por Roberto Serrano — Desarrollador web, automatizaciones e IA en Tarragona, España.
¿Te ha gustado? Compártelo.
Más sobre el tema
Artículos relacionados

Next.js 16.3 y Turbopack: de 21,5 GB a 2 GB de memoria en desarrollo
Turbopack en Next.js 16.3 recorta la memoria de desarrollo hasta un 90 %: de 21,5 GB a 2 GB. Benchmarks reales, configuración exacta y avisos clave.

TypeScript 7: el compilador nativo en Go y qué cambia en tu día a día
TypeScript 7 compila hasta 12 veces más rápido gracias a su port nativo a Go: benchmarks reales, nuevos defaults y checklist para migrar tu tsconfig.

OpenCode + GitHub Actions: Casos prácticos, multi-review y automatizaciones avanzadas
Ve más allá de /oc fix this. Configura reviews multi-agente, custom agents y workflows programados con OpenCode y GitHub Actions.