Hard20 minExpress.js Fundamentals
UpdatedAug 5, 2026
Edit

Express Graceful Shutdown

Question Variations

  • "What should an Express service do when it receives `SIGTERM`?"
  • "Why can calling `process.exit()` immediately lose requests?"
  • "How does readiness relate to graceful shutdown?"

Why This Is Asked

Stopping a Node process safely is an operational concern that appears in production and containerized deployments. Interviewers assess whether you protect in-flight requests and dependent resources during termination.

Key Concepts

  • Stop accepting new connections before closing application dependencies.
  • Let in-flight requests finish within a bounded timeout.
  • Handle SIGTERM and SIGINT idempotently.
  • Readiness should fail before a process is removed from service.

Question Variations

  • “What should an Express service do when it receives SIGTERM?”
  • “Why can calling process.exit() immediately lose requests?”
  • “How does readiness relate to graceful shutdown?”

Answers by Technology

+ Add Variant
Express.jsImprove this answer ✏️

Expected Answer (Express 5.1.0 / Node.js 18+)

On SIGTERM or SIGINT, an Express service should begin draining rather than exit immediately. Mark the process unready so the load balancer stops sending new work, call server.close() to stop accepting new connections, and allow existing requests to finish. Then close database pools, queues, and telemetry exporters. The shutdown path must have a deadline: if a request never finishes, log the failure and force termination after the orchestrator’s grace period.

Make the handler idempotent because a process can receive more than one signal. server.close() does not close every long-lived or idle connection in every deployment, so production services may also track sockets or use server timeouts. Avoid process.exit() before asynchronous cleanup completes; setting process.exitCode after cleanup is safer.

Why It Matters

Graceful shutdown avoids dropped writes, half-finished responses, and corrupted background work during deploys and autoscaling events.

Code Example

import express from 'express';

const app = express();
app.get('/', (_req, res) => res.send('ok'));
const server = app.listen(3000);
let stopping = false;
async function shutdown() {
  if (stopping) return;
  stopping = true;
  server.close(() => { process.exitCode = 0; });
  setTimeout(() => process.exit(1), 25_000).unref();
}
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);

Common Mistakes

  • Calling process.exit() as soon as a signal arrives: In-flight responses and async cleanup are abandoned.
  • Closing the database before draining HTTP: Active handlers can fail while they are still using the pool.

Follow-up Questions

  • What should readiness return while draining? (Answer: A failing response so new traffic is removed before dependencies are closed.)
  • Why is a timeout needed? (Answer: A stuck request must not prevent a replacement deployment forever.)