Node.js › Global Objects & the process Object

How do you correctly handle OS signals like SIGTERM and SIGINT in a Node.js application to implement graceful shutdown?

Advanced

Answer

process.on('SIGTERM', ...) and process.on('SIGINT', ...) let an application intercept termination signals sent by an orchestrator (SIGTERM, typically during a deployment or scale-down) or a user pressing Ctrl+C in a terminal (SIGINT), giving the application a chance to stop accepting new work, finish in-flight requests, close database connections cleanly, and only then actually exit -- without a handler, Node.js's default behavior for these signals is to terminate the process immediately, potentially interrupting in-progress work abruptly.
let server;

function gracefulShutdown(signal) {
  console.log(`Received ${signal}, shutting down gracefully...`);
  server.close(() => {
    db.close();
    process.exit(0);
  });
  setTimeout(() => process.exit(1), 10000); // force exit if graceful shutdown hangs
}

process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
Real-world example A Kubernetes-deployed API implements a SIGTERM handler that stops accepting new HTTP connections and waits for in-flight requests to complete (with a hard timeout fallback), ensuring rolling deployments never abruptly cut off a customer's in-progress checkout request mid-transaction.

Common follow-ups: Why is a hard timeout fallback (forcing exit after N seconds) an important safety net alongside graceful shutdown logic?;How much time does Kubernetes give a pod between sending SIGTERM and forcibly sending SIGKILL by default, and how does that affect your shutdown timeout budget?