Graceful shutdown of golang web server
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
A graceful shutdown lets a Go web server stop accepting new requests while allowing in-flight requests to finish within a deadline. This is important in production because abrupt termination can drop active connections, interrupt writes, and leave background work half-finished.
In Go's net/http package, the core tool for this is http.Server.Shutdown, usually combined with signal handling and a timeout context.
Why Server.Close Is Not Enough
Server.Close stops the server immediately by closing active listeners and connections. That is sometimes acceptable for local tools, but it is not graceful.
For graceful behavior, use:
- '
ListenAndServeto run the server' - signal handling for
SIGINTorSIGTERM - '
Shutdownto stop cleanly with a deadline'
Shutdown tells the server to reject new connections and wait for existing handlers to return.
A Minimal Graceful Shutdown Example
This is the standard shape for graceful shutdown in a Go HTTP service.
What Shutdown Actually Does
When Shutdown is called:
- listeners stop accepting new connections
- idle connections are closed
- active handlers are allowed to complete until the context expires
If the timeout is reached, Shutdown returns an error. At that point you may choose to force Close.
This is why the timeout matters. Without it, shutdown could hang indefinitely if handlers never return.
Handling Background Work
Graceful shutdown is not only about HTTP handlers. Many services also run:
- worker goroutines
- message consumers
- database flush loops
- telemetry exporters
Those components should also listen for cancellation and exit cleanly. A common pattern is to share a root context or a stop channel with background workers.
Example worker:
If the HTTP server shuts down gracefully but background goroutines ignore cancellation, the process may still hang or exit uncleanly.
Choosing a Timeout
The timeout should be long enough for normal requests to finish, but short enough that deployments and restarts do not stall forever.
A common production choice is somewhere between a few seconds and a few tens of seconds, depending on:
- request duration
- database transaction patterns
- load balancer drain time
- background cleanup needs
There is no single perfect value. It should reflect real request behavior.
Common Pitfalls
The biggest pitfall is calling Shutdown without running the server in a separate goroutine. If ListenAndServe blocks the main goroutine, the shutdown signal handling never gets a chance to run.
Another issue is forgetting the timeout context. Without a deadline, a stuck handler can prevent shutdown forever.
Developers also sometimes assume Shutdown stops background goroutines automatically. It does not. Only the HTTP server lifecycle is managed unless you wire cancellation into the rest of the program.
Finally, do not treat http.ErrServerClosed as a fatal startup failure. It is the expected return from ListenAndServe after a normal shutdown begins.
Summary
- Use
http.Server.Shutdownfor graceful Go web server shutdown. - Handle OS signals and trigger shutdown from a separate control path.
- Always use a timeout context so shutdown cannot hang forever.
- Stop background goroutines explicitly;
Shutdownonly manages the HTTP server. - Reserve
Server.Closeas a forced fallback when graceful shutdown times out.
Related reading
- Hardware requirement for apache kafka
- Has Django served an excess of 100k daily visits?
- Hazelcast SlowOperationDetector to identify operations with less than 1 sec execution time
- Heartbeat session expired, marking coordinator dead
- Helm - Templating variables in values.yaml
- Helm 3 delete deployment by deleting the namespace
- Helm _helpers.tpl Calling defined templates in other template definitions
- Helm Chart pass variable to dependency

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.