MediumπŸ‘€ 3-5 yearsπŸ‘€ 8-15 years 3 min read Updated Aug 24, 2026

How to Use a JVM Shutdown Hook to Drain In-Flight Requests

Asked inAmazonMicrosoft
#shutdown hook#graceful shutdown#sigterm#drain#kubernetes
Report issue

⚑ Short Answer

Runtime.getRuntime().addShutdownHook(thread) registers a thread the JVM runs during an orderly shutdown β€” SIGTERM, normal exit, or System.exit() β€” but never on SIGKILL or a crash. Use it to stop accepting new work, wait (with a bounded timeout) for in-flight requests to finish, then release resources, all inside whatever grace period your orchestrator gives the process before force-killing it.

β˜•Coffee Chat Question

Concept Made Simple

β€œHow do you use a JVM shutdown hook to drain in-flight requests before exit?”

🧠Mind Map Answer

Remember It Faster

A shutdown hook is a Thread registered via Runtime.getRuntime().addShutdownHook(hook) that the JVM starts the moment it begins an orderly shutdown β€” normal main() return, System.exit(), or a signal like SIGTERM (Ctrl+C, kill, a Kubernetes pod being terminated). It never runs on SIGKILL/kill -9 or a native crash β€” there's no orderly shutdown sequence for those to hook into.

Runs on→SIGTERM, System.exit(), normal exit
Does NOT run on→kill -9 / SIGKILL, native crash
Typical use→stop new work → drain in-flight → close resources

Kubernetes sends SIGTERM, then waits terminationGracePeriodSeconds (default 30s) before escalating to SIGKILL. A shutdown hook that takes longer than that window to drain gets killed mid-drain regardless of how correct its logic is β€” the grace period is a hard budget, not a suggestion.

java
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    log.info("SIGTERM received, draining...");
    server.stopAcceptingNewConnections();
    boolean drained = server.awaitInFlightRequests(Duration.ofSeconds(25));
    if (!drained) log.warn("Forced shutdown with requests still in flight");
    connectionPool.close();
}, "shutdown-hook"));

Key takeaway: the hook's job is sequencing, not magic β€” stop the front door first so the in-flight count can only shrink, then wait for it to hit zero (bounded), then release resources. Skip the 'stop accepting new work' step and the hook can chase a moving target until the grace period runs out.

πŸ”₯What If?

Think Beyond the Expected

Your shutdown hook takes 45s to drain but terminationGracePeriodSeconds is 30s β€” what happens?

Kubernetes sends SIGKILL at 30s regardless of the hook's progress β€” the JVM is killed mid-drain, and any requests still in flight at that instant are simply lost or reset from the client's perspective. Either shorten the drain budget to comfortably fit inside the grace period, or raise terminationGracePeriodSeconds to match the realistic worst case.

πŸ˜‚Real World

Every rolling deployment on Kubernetes or ECS depends on exactly this: a pod gets SIGTERM before it's removed from the load balancer's rotation and terminated, and a well-written shutdown hook is the difference between a clean deploy and a burst of connection-reset errors on every release.

πŸ—£οΈReal Talk from Guru

I treat the shutdown hook's timeout as a real SLA, not a nice-to-have β€” I set it a few seconds under whatever the orchestrator's grace period is, log clearly when a shutdown was forced instead of clean, and alert on that log line. If forced shutdowns are common in practice, that's a signal the drain budget or the grace period needs to change, not something to quietly tolerate.

🎯Interviewer's Expectation

Keywords they're listening for:

βœ“ addShutdownHook runs on SIGTERM/normal exit, not SIGKILLβœ“ stop accepting new work before draining old workβœ“ drain wait must be bounded by a timeoutβœ“ orchestrator grace period must exceed worst-case drain time

⚠️Common Mistakes

  • βœ—Assuming the shutdown hook always runs (it doesn't on SIGKILL or a crash)
  • βœ—No timeout on the drain wait, so the hook can block indefinitely on one stuck request
  • βœ—terminationGracePeriodSeconds shorter than the realistic worst-case drain time
  • βœ—Draining before stopping new connections, so the in-flight count never actually reaches zero

βœ…Best Practices

  • βœ“Stop accepting new connections first, then drain existing ones
  • βœ“Bound the drain wait with a timeout comfortably under the orchestrator's grace period
  • βœ“Log (and alert on) forced/incomplete shutdowns for visibility

πŸ”Follow-up Questions

  • 1What signal does Kubernetes send before force-killing a pod?
  • 2Why doesn't a shutdown hook run on kill -9?
  • 3How do you make an HTTP server stop accepting new connections but finish existing ones?
  • 4What happens if the shutdown hook itself throws an exception?

🧩Related Technologies

Runtime.addShutdownHookSIGTERMKubernetes terminationGracePeriodSecondsconnection draining

Continue Learning with AI

Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly β€” AI is your learning companion, not a shortcut.

Plain-language foundations

I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner.

Topic: Runtime (JVM)
Interview question: "How do you use a JVM shutdown hook to drain in-flight requests before exit?"

Please:
1. Explain the core idea in simple, plain language, using an everyday analogy.
2. Define any technical terms you use.
3. Walk through one small, concrete example.
4. Finish with a single sentence I can easily remember.

Keep the tone friendly and assume I'm new to this topic.

Was this answer helpful?

Support our platform by exploring our recommended products.

As an Amazon affiliate, purchases through these links may earn us a small commission β€” at no extra cost to you. It helps keep Full Stack Interview Guru free.

Related Questions