AceDevHub
Advanced Node.js Interview QuestionsAdvancedScenario

Node.js · Question 92

How would you implement graceful shutdown for a production Node.js server?

Direct answer

On SIGTERM: stop readiness, server.close() to drain HTTP, await in-flight requests with timeout, close pg pool and Redis, stop BullMQ worker, force exit after deadline — coordinate with K8s preStop and load balancer health checks.

Scenario: deploy new AceDevHub API version without dropping active requests — Docker sends SIGTERM; you have ~30s termination grace.

  1. Signal trap — SIGTERM + SIGINT handlers (Q73).
  2. Stop accepting — server.close(); mark /health/ready false.
  3. Drain work — track activeRequests counter; wait or timeout.
  4. Close deps — pool.end(), redis.quit(), worker.close().
  5. Force exit — process.exit(1) after 30s if stuck.
scenario-shutdown.mjs
let active = 0;
let shuttingDown = false;

fastify.addHook("onRequest", async () => { active += 1; });
fastify.addHook("onResponse", async () => { active -= 1; });

async function shutdown(signal) {
  if (shuttingDown) return;
  shuttingDown = true;
  fastify.log.info(`${signal} — shutting down (${active} active)`);

  await fastify.close();
  while (active > 0) await new Promise((r) => setTimeout(r, 100));

  await pool.end();
  await redis.quit();
  process.exit(0);
}

process.on("SIGTERM", () => shutdown("SIGTERM"));