El ciclo de vida del proceso de Node.js
Ejecutar un servicio de Node.js en producción no es la misma habilidad que escribir uno.
Busca en todas las páginas de la documentación
Ejecutar un servicio de Node.js en producción no es la misma habilidad que escribir uno.
Un script que funciona perfectamente con node app.js en una laptop aún puede fallar en el despliegue de un orquestador, perder solicitudes en curso en cada despliegue o colgarse indefinidamente al apagarse, porque ninguna de esas fallas reside en la lógica de la aplicación. Residen en el ciclo de vida del proceso: la secuencia por la que pasa un proceso de Node desde el momento en que un supervisor lo inicia hasta el momento en que sale, y las señales y comprobaciones de las que depende esa secuencia.
Esta página es el modelo mental subyacente a todo lo demás en esta sección. Conceptos básicos de operaciones en tiempo de ejecución presenta ejemplos prácticos de puntos de conexión de salud y manejadores de apagado; Apagado elegante, Despliegues sin tiempo de inactividad y PM2 y systemd profundizan en una etapa cada uno. Aquí, el objetivo es la forma de todo el ciclo de vida y por qué un orquestador, no el código de tu aplicación, es quien lo impulsa.
SIGTERM o un supervisor con un período de gracia demasiado corto rompe el contrato desde cualquier lado.Un proceso de Node es, a nivel del sistema operativo, nada especial: es un proceso del sistema operativo, con un PID, al que el sistema operativo puede enviar señales y que eventualmente sale con un código de estado.
Lo que hace que las "operaciones en tiempo de ejecución" sean una disciplina propia es que en producción este proceso nunca se ejecuta solo. Se encuentra dentro de un supervisor (systemd, PM2, un kubelet de Kubernetes, el plano de control de una plataforma sin servidor) cuyo único trabajo es decidir cuándo iniciarlo, cuándo enrutarle tráfico, cuándo detenerlo y cuándo reiniciarlo si muere inesperadamente.
Esa relación de supervisor replantea lo que significa "detener un servidor". En una laptop, detener significa Ctrl+C y el proceso desaparece. En producción, detener es una negociación: el supervisor le pide al proceso que se detenga, y el proceso tiene un período de tiempo para terminar lo que está haciendo antes de que el supervisor fuerce la situación.
Una analogía útil es un cambio de turno en el mostrador de un restaurante. El camarero saliente no se va en medio de un pedido en el momento en que termina su turno; deja de tomar nuevos pedidos, termina los pedidos que ya tiene en mano y solo entonces ficha. El gerente (el supervisor) establece una fecha límite para esa entrega; si el camarero todavía está allí cuando pasa la fecha límite, el gerente interviene y cierra la caja de todos modos. La secuencia de apagado de un proceso de Node sigue la misma forma: dejar de aceptar nuevo trabajo, terminar el trabajo en curso y luego salir, todo dentro de un período de gracia que otra persona controla.
El ciclo de vida tiene cinco etapas, y cada una es impulsada por una señal o comprobación diferente:
inicio ──▶ listo ──▶ sirviendo ──▶ drenando ──▶ salida
│ │ │ │ │
proceso sonda de manejo de SIGTERM código de
arranca preparación solicitudes recibida, proceso 0
pasa normal detener nuevo (o SIGKILL
trabajo, después del
finalizar período de
en curso gracia)
Inicio es el arranque del proceso: carga de módulos, análisis de configuración, apertura de pools de bases de datos. Nada debería servir tráfico todavía, porque las dependencias pueden no estar conectadas.
Listo es el punto en el que una sonda de preparación (un punto de conexión HTTP como /ready, o una comprobación equivalente) comienza a devolver éxito. Esta es una pregunta diferente de la vivacidad: la vivacidad pregunta "¿el proceso sigue ejecutándose y no está bloqueado?", mientras que la preparación pregunta "¿se le debe enrutar tráfico ahora mismo?". Un proceso puede estar vivo pero no listo (por ejemplo, aún abriendo un pool de conexiones a la base de datos), y un orquestador que confunda ambos enrutará solicitudes a un proceso que no está preparado para manejarlas.
Sirviendo es el manejo de solicitudes en estado estable, la etapa en la que un proceso pasa la mayor parte de su vida.
Drenando comienza en el momento en que el proceso recibe SIGTERM, la señal de "por favor, detente" a nivel del sistema operativo que todo supervisor envía antes de una detención, reducción de escala o despliegue. Esta es la etapa en la que residen la mayoría de los errores de operaciones en tiempo de ejecución, porque requiere que el proceso haga varias cosas en orden: cambiar la sonda de preparación a fallida (para que el balanceador de carga deje de enviar nuevas solicitudes), dejar de aceptar nuevas conexiones, permitir que las solicitudes en curso finalicen, cerrar recursos como pools de bases de datos de forma limpia y solo entonces salir. Apagado elegante cubre esa secuencia por completo.
let ready = true;
process.on('SIGTERM', async () => {
ready = false; // la sonda de preparación ahora falla - el balanceador de carga deja de enrutar aquí
server.close(async () => { // deja de aceptar nuevas conexiones; espera a las que están en curso
await dbPool.end(); // cierra los recursos solo después de que las solicitudes finalicen
process.exit(0);
});
});La razón por la que este orden importa es el propio bucle de eventos: el bucle de Node mantiene un proceso vivo exactamente mientras tenga temporizadores pendientes, manejadores abiertos o trabajo sin terminar (consulta El bucle de eventos de Node.js). Llamar a server.close() no elimina las conexiones en curso; detiene al servidor de aceptar nuevas y permite que el bucle siga ejecutándose hasta que las solicitudes existentes se completen de forma natural, que es precisamente el comportamiento de drenaje que espera un supervisor.
Salida es la etapa final, ya sea un process.exit(0) limpio una vez que finaliza el drenaje, o un SIGKILL del supervisor si el proceso no terminó dentro de su período de gracia. SIGKILL no se puede interceptar ni retrasar; es la garantía contundente del supervisor de que un proceso atascado no bloqueará un despliegue indefinidamente.
El modelo de ciclo de vida parece simple de forma aislada, pero la producción añade casos extremos reales a su alrededor.
Las excepciones no capturadas y las promesas rechazadas sin manejar no encajan limpiamente en ninguna de las cinco etapas; se supone que son excepcionales. La propia guía de Node es que una vez que se dispara una uncaughtException, el estado interno del proceso puede estar corrupto de maneras que no son seguras para seguir sirviendo; el patrón seguro es registrar el error, intentar un apagado limpio rápido y dejar que el supervisor reinicie un proceso nuevo, en lugar de intentar "capturar y continuar" indefinidamente.
Múltiples etapas de supervisión a menudo se apilan. Un contenedor podría ejecutarse bajo PM2 para reinicios a nivel de proceso, dentro de un pod administrado por Kubernetes para programación y escalado, detrás de un balanceador de carga que posee su propia cadencia de comprobación de salud, cada capa haciendo una versión de "¿esta instancia está lista?" de forma independiente, y cada una con su propio tiempo de espera que debe ser más largo que el que está debajo o los apagados compiten entre sí.
El período de gracia es un número operativo real, no un valor predeterminado que se debe dejar solo. Demasiado corto, y las solicitudes lentas se eliminan a mitad de vuelo durante cada despliegue; demasiado largo, y un proceso genuinamente atascado bloquea un despliegue o una reducción de escala durante minutos. Acertar con este número requiere conocer la duración real de tu solicitud p99 bajo carga, no adivinar.
La observabilidad es el bucle de retroalimentación que hace que todo este modelo sea confiable. Los registros estructurados a stdout, los ID de solicitud y las métricas a nivel de proceso (retraso del bucle de eventos, memoria, manejadores abiertos) son lo que permite a un operador confirmar que un despliegue se drenó limpiamente en lugar de asumir que lo hizo.
| Supervisor | Fortaleza | Debilidad | Mejor ajuste |
|---|---|---|---|
| systemd | Nativo de la VM, sin tiempo de ejecución adicional, políticas de reinicio maduras | No tiene enrutamiento de comprobación de salud ni escalado incorporados | VMs de un solo servicio, despliegues simples en hardware básico |
| PM2 | Recarga sin tiempo de inactividad incorporada, modo clúster fácil en una sola máquina | No es un orquestador real: no hay programación multi-host | Equipos pequeños con unas pocas VMs, sin Kubernetes |
| Kubernetes | Probes de vivacidad/preparación, despliegues continuos, autoescalado, multi-host | Complejidad operativa real; mucho que aprender y ejecutar | Flotas de múltiples servicios que necesitan escalado y auto-reparación |
| Serverless (ej. Lambda) | No hay ciclo de vida del proceso que gestionar en absoluto: la plataforma se encarga del inicio/parada | Arranques en frío, límites de tiempo de ejecución, modelo mental completamente diferente | Cargas de trabajo intermitentes o poco frecuentes, funciones basadas en eventos |
PM2 y systemd y Despliegues sin tiempo de inactividad convierten esta comparación en configuración concreta; Guías de inicio para el Runbook de guardia cubre qué comprobar cuando una transición del ciclo de vida falla en producción.
SIGTERM significa que el proceso está siendo eliminado." Significa que el supervisor le está pidiendo al proceso que se detenga; se espera que el proceso termine el trabajo en curso primero; SIGKILL, no SIGTERM, es la señal forzosa y no puede ser interceptada.server.close() elimina cualquier solicitud que aún esté en curso." Detiene la aceptación de nuevas conexiones; las solicitudes que ya se están manejando se completan normalmente porque el bucle de eventos permanece vivo hasta que lo hacen.La secuencia por la que pasa un proceso bajo supervisión (inicio, listo, sirviendo, drenando, salida), donde un supervisor externo, no el propio proceso, decide cuándo deben comenzar la mayoría de las transiciones.
En una laptop, nada más depende del momento exacto de detención del proceso. En producción, un balanceador de carga le está enrutando tráfico en vivo, un despliegue está tratando de reemplazarlo sin perder solicitudes, y un orquestador necesita una señal confiable para saber cuándo es seguro enrutar tráfico allí, nada de lo cual existe fuera de un entorno supervisado.
La vivacidad pregunta "¿debe reiniciarse este proceso porque algo anda mal?", mientras que la preparación pregunta "¿debe enrutarse tráfico aquí ahora mismo?". Un proceso que abre un pool de bases de datos al inicio está vivo pero aún no listo; un proceso bloqueado en un bloqueo aún podría responder a una comprobación de vivacidad sin poder atender solicitudes reales, por lo que algunos equipos añaden una comprobación de vivacidad más estricta también.
El supervisor (systemd, Kubernetes, PM2) envía la señal SIGTERM a nivel del sistema operativo al PID del proceso. Node expone esto como un evento process.on('SIGTERM', ...) que puedes manejar; sin un manejador, el comportamiento predeterminado de Node es salir inmediatamente, lo que omite cualquier drenaje.
server.close() detiene al servidor de aceptar nuevas conexiones, pero no fuerza el cierre de las existentes; el bucle de eventos sigue ejecutándose porque esas solicitudes en curso siguen pendientes, y el proceso solo sale una vez que terminan y se libera cada manejador abierto.
El período de gracia del supervisor expira y envía SIGKILL, que termina el proceso inmediatamente y no puede ser interceptado, retrasado o limpiado después; cualquier solicitud que aún esté en curso en ese momento se pierde.
Generalmente no; una excepción no capturada significa que un error escapó a todos los manejadores en la pila de llamadas, lo que puede dejar el estado interno (conexiones abiertas, datos en memoria actualizados a medias) en una condición desconocida. El patrón más seguro es registrarlo, apagar limpiamente y dejar que el supervisor inicie un proceso nuevo.
El código de manejo de señales en tu aplicación es el mismo en ambos casos; es el comportamiento del supervisor lo que difiere. Kubernetes añade un punto de conexión de sonda de preparación que la aplicación debe exponer y un período de gracia definido (terminationGracePeriodSeconds) que el clúster aplica, además del mismo patrón SIGTERM-luego-SIGKILL que también usan systemd y PM2.
Generalmente porque la sonda de preparación no cambia a fallida lo suficientemente pronto en la secuencia de drenaje, por lo que el balanceador de carga sigue enviando nuevas solicitudes a una instancia que ya ha comenzado a apagarse; la solución es el orden: primero falla la preparación, luego deja de aceptar conexiones, luego permite que el trabajo en curso finalice.
No; un fallo es una salida no planificada, generalmente por un error no capturado o por ser eliminado sin previo aviso, mientras que un apagado elegante es una secuencia planificada y controlada por señales en la que el proceso controla el ritmo (dentro de su período de gracia). Las herramientas de operaciones en tiempo de ejecución asumen que los fallos son excepcionales y los apagados son rutinarios.
El bucle de eventos solo sale una vez que no tiene temporizadores pendientes, ni manejadores abiertos (como un servidor escuchando o un socket abierto), ni E/S en cola; cada uno de ellos es efectivamente un voto para mantener el proceso vivo, por lo que los manejadores filtrados (una conexión de base de datos no cerrada, por ejemplo) pueden evitar que un proceso salga limpiamente.
Solo de forma laxa; una plataforma sin servidor posee el ciclo de vida de inicio/parada por completo y normalmente no te da ninguna ventana de manejo de señales, por lo que la etapa de "drenaje" en su mayoría no se aplica. Aún así, vale la pena conocer el modelo, porque mover un servicio de larga duración a sin servidor (o viceversa) significa razonar sobre un ciclo de vida genuinamente diferente, no solo un objetivo de despliegue diferente.
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa) y TypeScript 5.6+.
Revisado por Chris St. John·Última actualización: 15 jul 2026