Development10 min read0 visualizaciones

    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

    Roberto Serrano

    Ingeniero de Software

    Node.js

    ¿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ónEstadoDetalle
    Node 24.0.0Current (2025-05-06)Publicado por Rafael Gonzaga y Juan Arbol
    Node 24.11.0Entrada 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»LTSv22.23.3 (23-sep-2026), sigue siendo válido
    Node 25EOL (31-mar-2026)Fuera de soporte
    Node 26Current (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 using y await 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.
    • SlowBuffer deprecado.
    • test_runner ya no devuelve promesas.
    • Cambios en los argumentos de child_process.spawn y execFile.
    • fs.existsSync con tipos inválidos y fs.truncate con descriptor de fichero (usa ftruncate).
    • _headers y _headersList de http.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.

    1. Fija la versión objetivo: Node 24.22.0 o superior del árbol 24.
    2. Audita TLS: revisa que ningún servicio con el que hablas use claves por debajo de 2048 bits RSA o 224 bits ECC.
    3. Recompila addons nativos y verifica compatibilidad con NODE_MODULE_VERSION 137.
    4. Ejecuta --permission-audit en un entorno de pruebas para descubrir qué permisos necesita realmente tu aplicación.
    5. Revisa el uso de fetch(), stream, pipe y AbortSignal.
    6. Pasa los codemods oficiales (siguiente sección).
    7. Comprueba child_process y test_runner si los usas en tests.
    8. Actualiza la imagen base y el toolchain si compilas en CI.
    9. 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-file y --openssl-config se 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

    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