{"post":{"slug":"graceful-shutdown-explained-2026","title":"Graceful shutdown explained in 2026: draining without data loss","excerpt":"A graceful shutdown stops a process without dropping work in flight. This 2026 guide covers SIGTERM versus SIGKILL, the four-step drain pattern, grace periods, and the pitfalls that lose data.","category":"code","date":"June 29, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">G</span>raceful shutdown is the discipline of stopping a running program without dropping work in flight. When a process gets a termination signal, the naive response is to die immediately — but that can cut off open requests, corrupt partial writes, and leave queues in a half-processed state. A graceful shutdown instead stops accepting new work, finishes what it already started, releases resources, and then exits.\n\n## What changed in 2026\n\n- **Orchestrators made signals unavoidable.** Kubernetes, serverless platforms, and autoscalers routinely start and stop instances. Handling SIGTERM correctly is now table stakes, not a nicety.\n- **Shorter grace periods are common.** Platforms tightened default termination windows to speed up rollouts, so shutdown logic has to be fast and bounded, not open-ended.\n- **Structured lifecycle hooks spread.** Frameworks across languages standardized on explicit startup and shutdown hooks, making it easier to register cleanup without hand-rolling signal handlers.\n\n## How graceful shutdown works\n\nThe pattern is almost always the same four steps:\n\n1. **Catch the signal.** The platform sends SIGTERM (and later SIGKILL if you ignore it).\n2. **Stop accepting new work.** Close the listener, stop pulling from the queue, and fail readiness checks so the load balancer stops routing to you.\n3. **Drain in-flight work.** Let open requests or jobs finish, up to a deadline.\n4. **Release resources and exit.** Close database pools, flush logs and buffers, then exit cleanly.\n\nA minimal Go-style sketch:\n\n```go\nsig := make(chan os.Signal, 1)\nsignal.Notify(sig, syscall.SIGTERM)\n<-sig\nserver.Shutdown(ctxWithTimeout) // stop new, drain existing\ndb.Close()\n```\n\nThe key idea: shutdown must be *bounded*. If draining takes longer than the grace period, the platform sends SIGKILL and you lose the remaining work anyway.\n\n## SIGTERM vs SIGKILL\n\n| | SIGTERM | SIGKILL |\n| --- | --- | --- |\n| Catchable | Yes | No |\n| Intent | Please stop cleanly | Stop now |\n| Who sends it first | Orchestrator on shutdown | Orchestrator after grace period |\n| Your job | Drain and clean up | Nothing — you are gone |\n\nThe whole point of graceful shutdown is to finish your work during the SIGTERM window so SIGKILL never has to be used.\n\n## When it matters most\n\nGraceful shutdown matters any time losing in-flight work has a cost: HTTP servers with open requests, workers pulling from a queue, streaming consumers holding offsets, and anything mid-write to a database. It matters less for stateless, idempotent jobs that can simply be retried — though even there, closing connections cleanly avoids noisy errors. Long-lived connections and background jobs are the trickiest; those often interact with concurrency issues covered in [race conditions](/blog/race-conditions-explained-2026).\n\n## Common pitfalls\n\n- **Failing readiness too late.** If you keep passing health checks while shutting down, the load balancer keeps sending traffic into a dying process. Fail readiness first.\n- **Unbounded drains.** Waiting \"until everything finishes\" invites a SIGKILL mid-cleanup. Always set a deadline shorter than the grace period.\n- **Ignoring buffered writes.** Logs, metrics, and batched writes sitting in memory are lost if you exit before flushing. Flush explicitly.\n- **Blocking the signal handler.** Doing heavy synchronous work directly in the handler can deadlock. Signal, then coordinate shutdown in the main flow.\n\n## FAQ\n\n**What signal should I handle for shutdown?**\nSIGTERM is the standard \"please stop\" signal from orchestrators and init systems. Also handle SIGINT for local Ctrl-C. You cannot catch SIGKILL.\n\n**How long should a graceful shutdown take?**\nShorter than the platform grace period (often around 30 seconds by default). Set your drain deadline a few seconds under that so cleanup still runs.\n\n**What is the difference between draining and shutting down?**\nDraining is the middle step: refusing new work while finishing existing work. Shutdown is the whole lifecycle, ending in process exit.\n\n**Do stateless services need graceful shutdown?**\nLess critically, but still yes — closing connections and flushing logs cleanly avoids error spikes during every deploy and scale-down.\n\n## Where to go next\n\n- [Synchronous vs asynchronous programming in 2026](/blog/synchronous-vs-asynchronous-programming-2026)\n- [Blue-green vs canary deployment in 2026](/blog/blue-green-vs-canary-deployment-2026)\n- [CI vs CD in 2026](/blog/ci-vs-cd-2026)","hue":260,"metaTitle":"Graceful Shutdown Explained 2026: A Practical Guide","metaDescription":"Graceful shutdown 2026 explained: catch SIGTERM, stop new work, drain in-flight requests, and exit clean before SIGKILL so you never lose data.","keywords":["graceful shutdown 2026","graceful shutdown explained","sigterm vs sigkill","how to handle sigterm","graceful shutdown kubernetes","draining requests on shutdown","graceful shutdown pattern","process lifecycle cleanup 2026"],"tldr":["**Graceful shutdown drains before exiting** — stop new work, finish in-flight work, release resources, then quit.","**SIGTERM is your window** — catch it and clean up before the platform sends an uncatchable SIGKILL.","**Shutdown must be bounded** — set a drain deadline shorter than the grace period.","**Fail readiness first** — so the load balancer stops sending traffic to a dying process.","**Skip:** heavy synchronous work inside the signal handler — signal, then coordinate shutdown in the main flow."],"readTime":"3 min read","wordCount":677},"related":[{"slug":"zero-downtime-deployment-guide-2026","title":"Zero-Downtime Deployment 2026: Not Dropping Requests","excerpt":"Zero-downtime deployment is not one technique, it is a checklist of every place an in-flight request can get dropped during a restart. Here is the full 2026 checklist, from SIGTERM to load balancer deregistration.","category":"code","date":"August 10, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":322},{"slug":"what-is-a-kubernetes-pod-2026","title":"What Is a Kubernetes Pod? Explained for 2026","excerpt":"A plain-language guide to what a Kubernetes pod is in 2026: how it wraps containers, why pods are disposable, and when to think about them at all.","category":"code","date":"April 30, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":145},{"slug":"what-is-a-pull-request-2026","title":"What is a pull request in 2026? How code review works on Git","excerpt":"A pull request is a proposal to merge your code changes into a shared branch, with built-in review. This guide explains how pull requests work and how to open a good one in 2026.","category":"code","date":"June 10, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":268}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"getting-things-done-gtd-2026","title":"Getting Things Done (GTD) in 2026: a practical guide","excerpt":"Getting Things Done is a five-step system for getting commitments out of your head and into a trusted place. Here is the 2026 guide to how GTD works and how to run a lightweight version of it.","category":"guides","date":"June 29, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":240},"older":{"slug":"habit-stacking-2026","title":"Habit stacking in 2026: building new routines onto old ones","excerpt":"Habit stacking anchors a new habit to one you already do, using an existing routine as the trigger. Here is the 2026 guide to how it works, how to write a stack, and where it breaks down.","category":"guides","date":"June 29, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":230}}