Versión de Node en Vercel: lo que .nvmrc no te dice
En pocas palabras: Vercel solo lee la versión de Node desde engines.node en package.json o desde el dropdown del dashboard, nunca desde .nvmrc. CogniPrep corrigió esta semana engines.node a “24.x” y .nvmrc a v24.22.1, tras meses con producción corriendo una línea distinta a la documentada en el repositorio.
La versión de Node en Vercel se define con engines.node en package.json o con el selector del dashboard, nunca con .nvmrc. CogniPrep, un sitio de Next.js que corre en Vercel, tenía ese archivo clavado en v22.22.2 mientras producción corría otra línea distinta, y la única fuente de verdad real era un dropdown de settings que nadie abría hacía meses.
engines.node es el campo de package.json que Vercel lee para decidir el major de Node.js del deploy; junto al setting del dashboard, es el único input documentado por Vercel para esa decisión. La plataforma solo deja fijar un major (22.x o 24.x), nunca un patch exacto: los minor y patch se actualizan solos, incluso por motivos de seguridad, sin que nadie lo pida.
En este artículo:
- En resumen
- ¿Por qué el archivo .nvmrc no cambia la versión de Node en Vercel?
- ¿Qué diferencia hay entre engines.node y .nvmrc en un proyecto Next.js?
- ¿Por qué Vercel ofrece Node 24.x y no 22.x como default en 2026?
- ¿Qué vulnerabilidades corrige la versión 24.22.1 de Node.js lanzada el 21 de octubre de 2026?
- ¿Cómo saber qué versión de Node corre una app en producción si no aparece en los headers?
- ¿Qué significa esto para equipos que no usan Vercel?
- Errores comunes al manejar la versión de Node en Vercel
- Preguntas Frecuentes
- Conclusión
- Fuentes
En resumen
- CogniPrep corrigió
engines.nodea “24.x” y actualizó.nvmrca v24.22.1 esta semana, después de meses con el dato real escondido en un dropdown de settings. .nvmrcno es un input de Vercel: solo sirve para que nvm fije el patch exacto en la laptop del desarrollador.- Node 24.22.1, lanzada el 21 de octubre de 2026, corrige 10 CVEs, 4 de severidad alta, incluido un out-of-bounds write en el decoder Brotli (CVE-2026-111497).
- Vercel solo ofrece rangos major (22.x o 24.x) para el deploy; no se puede pinnear un patch exacto en el dashboard.
- El endpoint
/api/healthde cogniprep.app no expone la versión de Node ni en headers ni en el body, por diseño de seguridad.
¿Por qué el archivo .nvmrc no cambia la versión de Node en Vercel?
.nvmrc no figura entre los inputs que Vercel documenta para elegir la versión de Node del deploy. Ese archivo lo lee nvm en una máquina local, nunca el build en la nube. Cubrimos ese tema en detalle en la contradicción de las credenciales estáticas en Vercel.
En CogniPrep, antes del commit de esta semana, .nvmrc decía v22.22.2 mientras producción corría en otra release line por completo. El repo tenía un patch exacto apuntando a una versión que el deploy ignoraba, y eso es peor que no tener archivo: se lee como documentación, pero miente. Según el post original de Daniel Pertu en dev.to, nadie lo notó porque la única fuente de verdad real vivía en un dropdown de settings sin abrir desde hacía meses.
¿Qué diferencia hay entre engines.node y .nvmrc en un proyecto Next.js?
engines.node en package.json, junto al setting del dashboard, define el major que usa el deploy en Vercel. .nvmrc define el patch exacto que debe usar nvm en el entorno local, porque nvm es el único consumidor capaz de actuar con esa precisión.
El fix de CogniPrep toca esto de forma literal: .nvmrc pasó de v22.22.2 a v24.22.1, y package.json sumó "engines": { "node": "24.x" }. No son archivos redundantes (parecen hacer lo mismo, pero no es así): uno le habla a Vercel, el otro le habla a tu terminal. Si solo tenés uno de los dos, te falta la mitad de la historia.
¿Por qué Vercel ofrece Node 24.x y no 22.x como default en 2026?
Node 24 (Krypton) es la LTS vigente y el default de Vercel en 2026, mientras Node 22 (Jod) sigue siendo LTS pero va de salida. Node 25 ya terminó su ciclo de vida en marzo de 2026, según la tabla de releases que mantiene el propio proyecto Node.js. Ya lo cubrimos antes en desplegar un proyecto React con Vite.
Vercel ofrece exactamente dos rangos: 24.x (default) y 22.x. Node 26 ya es Current, lo que lo posiciona como posible próxima LTS, pero todavía no está entre las opciones de producción. Entre las dos que sí están disponibles, una va de salida y la otra es la LTS activa: la elección se hace sola.
¿Qué vulnerabilidades corrige la versión 24.22.1 de Node.js lanzada el 21 de octubre de 2026?
Node 24.22.1 corrige 10 CVEs, 4 de severidad alta, el más grave un out-of-bounds write en el decoder Brotli (CVE-2026-111497). Los mismos fixes se espejaron en 22.23.4 y 26.12.1, sin workaround publicado para ninguno de los diez.
Esto no es un detalle cosmético. Vercel va a aplicar ese patch por debajo de tu deploy sin pedirte permiso, que es el comportamiento correcto para un rollout de seguridad. El problema aparece cuando tu proyecto vive solo en un dashboard: no tiene dónde escribir que le importa. Para más detalles técnicos, mirá publicar tu web gratis en Vercel.
¿Cómo saber qué versión de Node corre una app en producción si no aparece en los headers?
Con un curl a los headers o al body de un health check público no se obtiene ninguna pista sobre el runtime. La única vía que documenta Vercel es loguear process.version durante el build, y eso solo informa sobre un deployment puntual, no sobre el proyecto en general.
El endpoint /api/health de cogniprep.app lo deja bastante claro. Los headers traen server: Vercel, un x-vercel-id, HSTS y una content security policy, nada de versión de Node. El body es un health check real, con database, redis, environment y monitoring, y la respuesta de base de datos se mueve en milisegundos cada vez que lo consultás. Cero información de runtime, y tiene sentido: publicar qué versión de Node corrés es reconocimiento gratis para cualquiera que esté leyendo una lista de CVEs recién publicada.
¿Y si no tenés acceso al dashboard? Entonces el repo es el único lugar donde la respuesta puede vivir, en los dos archivos que mencionamos arriba, cada uno haciendo el único trabajo que sabe hacer. Esto se conecta con lo que analizamos en comparar Vercel con AWS Amplify en números.
| Campo | Dónde vive | Quién lo lee | Qué define | ¿Permite patch exacto? |
|---|---|---|---|---|
| engines.node | package.json | Build de Vercel | Major de Node en producción | No, solo major (22.x / 24.x) |
| .nvmrc | Raíz del repo | nvm en la laptop del dev | Patch exacto en entorno local | Sí (ej: v24.22.1) |
| Setting del dashboard | Project Settings de Vercel | Build de Vercel (si no hay engines) | Major de Node en producción | No |

¿Qué significa esto para equipos que no usan Vercel?
Si tu stack corre en un VPS propio en vez de en una plataforma serverless, este problema en particular no existe porque vos controlás el runtime de punta a punta. Para equipos en Latinoamérica que están evaluando mover un proyecto Node fuera de un serverless, proveedores de hosting y VPS en Argentina como donweb.com son una alternativa a evaluar.
Errores comunes al manejar la versión de Node en Vercel
- Confiar en .nvmrc como documentación de producción. Vercel no lo lee en el build; si solo tenés ese archivo, el repo miente sobre qué corre en serio. Agregá siempre
engines.nodeexplícito. - Dejar @types/node apuntando a una versión mayor que el runtime real. En CogniPrep,
@types/nodeestaba en ^25.9.5 mientras el código corría en Node 24, una línea que ya había llegado a end of life en marzo de 2026. Los types adelantados no detectan bugs, los esconden: cualquier API agregada después de tu runtime tipea limpio y después explota con unTypeError: not a functionen una función serverless a las dos de la mañana. - Asumir que podés pinnear un patch exacto en Vercel. El dashboard y
engines.nodesolo aceptan major (24.x, 22.x), nunca 24.22.1. Si necesitás esa precisión, es trabajo de.nvmrcen local, no de Vercel en producción. - Ignorar el warning de engine mismatch en cada comando. Si tu laptop corre Node 26 y el proyecto declara 24.x, vas a ver un
[WARN] Unsupported engineen cadapnpm typecheck. Es molesto, pero es la única señal visible de que local y producción no coinciden. Sacarlo conengine-strict: falseno resuelve nada, solo te deja ciego otra vez.
Preguntas Frecuentes
¿Cómo defino la versión de Node.js que usa Vercel para el deploy?
Con el campo engines.node en package.json, por ejemplo "node": "24.x". Ese valor tiene prioridad sobre el setting del dashboard, y Vercel solo acepta rangos de major, nunca un patch exacto.
¿Para qué sirve el archivo .nvmrc si mi proyecto corre en Vercel?
Sirve únicamente para que nvm fije el patch exacto de Node en tu máquina local cuando corrés nvm use. Vercel no lo lee en ningún momento del build.
¿Por qué Vercel no permite fijar un patch exacto de Node, solo el major?
Porque Vercel aplica rollouts automáticos de minor y patch, incluso por seguridad, sin pedirte permiso. Dejar solo el major disponible evita que un proyecto quede clavado en un patch con una vulnerabilidad conocida sin parche.
¿Conviene usar Node 22 o Node 24 en 2026?
Node 24 (Krypton) es la LTS vigente y el default de Vercel en 2026. Node 22 (Jod) sigue siendo LTS pero va de salida, así que conviene migrar a 24.x si todavía no lo hiciste.
¿Cómo puedo saber qué versión de Node corre mi app en producción sin acceso al dashboard?
Revisando engines.node en el repo o logueando process.version durante el build, que es la vía que documenta Vercel. Los headers y los health checks públicos no exponen esa información por diseño de seguridad.
Conclusión
Lo que cambió en CogniPrep no es gran cosa en líneas de código (tres archivos, casi todo lockfile), pero resuelve algo que cualquiera que haya tocado un proyecto en Vercel se topó alguna vez: no tener forma de responder, clonando el repo, qué Node corre en producción. La solución es simple y queda documentada en el propio repositorio: engines.node declara el major que manda en el deploy, .nvmrc declara el patch que tu laptop debería usar, y ninguno de los dos reemplaza al otro.
Si tu proyecto en Vercel tiene .nvmrc pero no engines.node en package.json, revisalo hoy. Y si tenés @types/node apuntando a una versión mayor que tu runtime real, alineá ambos: los types adelantados no te salvan de nada, te tapan el error hasta que explota en producción.






