Question presented to candidate: "A deployment sends SIGTERM to your Node process while it is actively handling several requests. If you just call process.exit() immediately, what breaks — and what should happen instead?"
What a strong answer should cover:
- Graceful shutdown means: stop accepting new connections, let already-in-flight requests finish naturally, close database/other external connections cleanly, and only then exit the process — calling
process.exit()immediately on receiving a shutdown signal abandons any request currently mid-flight. - 📌 Verified, not assumed:
server.close(), called while a request was genuinely in flight, correctly rejected a brand-new connection attempt immediately, while the existing in-flight request was allowed to finish naturally and its response was received successfully — confirmed with real timing, not a description of the intended behavior. - 📌 A real, honest nuance worth flagging rather than glossing over:
server.close()'s own completion callback did not fire until roughly 3 seconds after the in-flight request had already finished — an observed consequence of an idle keep-alive connection remaining open, whichserver.close()alone waits out rather than forcibly closing. This is a real, practical trap: naive code waiting on that callback before exiting can hang far longer than the actual in-flight work required. - The standard pattern: listen for
SIGTERM/SIGINT, callserver.close(), close database connections and other external resources, and set an explicit timeout as a safety net — if graceful shutdown has not completed within a bounded window, force-exit anyway, rather than risking an indefinite hang from a lingering connection (exactly the kind of hang observed above). - This connects directly to the containerized-PID-1 signal-handling question: without an explicit
SIGTERMhandler, a process (especially one running as PID 1 in a container) may not respond to the shutdown signal at all, forcing the orchestrator to wait out its full grace period before a hardSIGKILL— the graceful-shutdown code described here is precisely what should run inside that handler. - A precise answer names that "graceful" specifically means giving in-flight work a bounded chance to finish, not an unbounded one — a hung connection or a runaway request should not be allowed to block shutdown forever, which is exactly the honest gap the verified keep-alive delay above illustrates concretely.
Clarifying questions expected:
- "Is this running in a container (with the PID-1 signal nuance) or a plain process managed by systemd/pm2?" — the SIGTERM-handling mechanics connect directly either way.
- "What external resources (database connections, message queue consumers) need explicit cleanup beyond the HTTP server itself?"
Code / implementation expected: Yes — the real, measured server.close() behavior (a new connection correctly refused, an in-flight request correctly allowed to finish, and the honestly-reported keep-alive delay before the completion callback) is the concrete, convincing demonstration.