PM2 graceful reload vs Node.js SIGTERM handling across versions
0 reputation · 09 Jul 2024, 05:27 UTC
Integration boundary
PM2's zero-downtime reload mechanism relies on sending SIGUSR2 to the master process, which then forwards SIGTERM to workers for graceful shutdown. The application must implement a SIGTERM handler that finishes in-flight requests before exiting. This contract sits at the boundary between PM2's process orchestration and the Node.js runtime's signal semantics.
Version-dependent behavior
Node.js v12 and v18+ differ in how they process signals during the event loop tick. In v12, a SIGTERM handler that calls server.close() may not drain connections before the process exits if the handler returns synchronously. In v18+, the same pattern can leave the process hanging if the handler does not explicitly call process.exit() after the server closes. PM2's reload timeout (default 1.6s) then kills the worker with SIGKILL, potentially dropping requests.
Unresolved decision
When migrating a small application to PM2 cluster mode without downtime, the team must choose a signal-handling strategy that works across the Node.js versions present in their CI/CD pipeline and production fleet. The documentation does not prescribe a version-agnostic pattern, and the listen_timeout and kill_timeout settings interact differently with each runtime.
What SIGTERM handler pattern guarantees request draining on both Node.js 12 and 18+ under PM2 reload? How should kill_timeout be tuned relative to the application's longest request latency to avoid premature SIGKILL? Does PM2's wait_ready flag change the signal sequence enough to simplify the handler?