[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f3rd6536cwuvab":3},{"id":4,"title":5,"description":6,"category":7,"contentHtml":8,"date":9,"createdAt":10,"updatedAt":11},"2fbbf043-1b2e-45ab-bfc9-b7eafd89926c","Graceful Shutdown in Golang","A practical guide to implementing graceful shutdown for Go HTTP servers. Learn what signals are, how Go handles termination under the hood, and how to properly shut down your server without dropping requests or corrupting data.","backend development","\u003Ch2>What is a Graceful Shutdown?\u003C\u002Fh2>\n\u003Cp>A graceful shutdown is the process where a system, service, or application is stopped in a managed and controlled manner, allowing it to finish processing active requests or jobs and close network connections properly.\u003C\u002Fp>\n\u003Cp>Unlike a forceful shutdown, which can interrupt running tasks and cause data loss, it ensures that all ongoing processes are completed before terminating the service.\u003C\u002Fp>\n\u003Ch3>Why We Need It\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Prevents Data Loss and Corruption\u003C\u002Fstrong>: If you cut the power or force-close an app while a process is writing to disk or performing some db operation, you can corrupt your file systems or leave incomplete data. A graceful shutdown gives the app time to finish writing and flush buffers.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Avoids Dropped User Requests\u003C\u002Fstrong>: In web servers, dropping a process instantly severs active connections. A graceful shutdown allows the Go server to stop accepting new requests while it completes in-flight ones.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>Seamless Deployments &#x26; Scaling\u003C\u002Fstrong>: In cloud environments, when using Docker or Kubernetes, instances are constantly spun up and down during rolling updates. Graceful shutdowns ensure instances properly terminate, avoiding downtime and user-facing errors.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2>Prerequisites\u003C\u002Fh2>\n\u003Cp>What do you need to follow this article?\u003C\u002Fp>\n\u003Col>\n\u003Cli>Working knowledge of Golang.\u003C\u002Fli>\n\u003Cli>Knowledge of HTTP.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2>Understanding Signals\u003C\u002Fh2>\n\u003Cp>Before we proceed, we need to understand how the operating system actually tells your application to stop. It does this through signals.\u003C\u002Fp>\n\u003Cp>A signal is a standardized asynchronous notification sent to a running process to inform it that an important event has occurred. These events can originate from the user (like pressing Ctrl+C), from the operating system, or even from other programs. When a signal is delivered, the OS interrupts the normal flow of the process to handle it.\u003C\u002Fp>\n\u003Ch3>How a Process Responds to Signals\u003C\u002Fh3>\n\u003Cp>When a process receives a signal, one of three things happens:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Signal handler\u003C\u002Fstrong>: The process can register a custom handler (a function) for a specific signal. When that signal comes in, the handler runs instead of the default behavior.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Default action\u003C\u002Fstrong>: If no custom handler is registered, the process follows the default behavior for that signal. Depending on the signal, this might mean terminating, stopping, continuing, or ignoring the process.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Unblockable signals\u003C\u002Fstrong>: Some signals, like SIGKILL, cannot be caught or ignored. They will always terminate the process, no matter what.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Common Signals\u003C\u002Fh3>\n\u003Cp>Here are the signals you will encounter most often:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>SIGINT\u003C\u002Fstrong> (Signal Interrupt): Sent when the user presses Ctrl+C in the terminal.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SIGTERM\u003C\u002Fstrong> (Signal Terminate): A polite request for a process to terminate. This is what Kubernetes sends to your pod during shutdown.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SIGKILL\u003C\u002Fstrong>: A forceful termination signal that cannot be caught or ignored.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SIGSEGV\u003C\u002Fstrong> (Segmentation Violation): Sent when a program attempts to access memory that doesn't belong to it.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SIGSTOP and SIGCONT\u003C\u002Fstrong>: Used to pause and resume process execution.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>SIGQUIT\u003C\u002Fstrong>: Quit signal (such as Ctrl+D).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>For our implementation, we mostly care about \u003Cstrong>SIGTERM\u003C\u002Fstrong> and \u003Cstrong>SIGINT\u003C\u002Fstrong>. SIGTERM is what orchestrators like Kubernetes send when they want your app to stop, and SIGINT is what you get when you press Ctrl+C in the terminal of your running server.\u003C\u002Fp>\n\u003Ch2>How Go Handles Termination\u003C\u002Fh2>\n\u003Cp>Now that we understand signals, let's look at what Go actually does when your app receives one.\u003C\u002Fp>\n\u003Cp>When your Go app gets a SIGTERM, the runtime first catches it using a built-in handler. It checks if a custom handler has been registered. If not, the runtime disables its own handler temporarily and sends the same signal (SIGTERM) to the application again. This time, the OS handles it using the default behavior, which is to terminate the process and clean up any remaining resources.\u003C\u002Fp>\n\u003Cp>The important thing to note here is that Go gives us the ability to intercept these signals before the default behavior kicks in. We can override the signal handling by registering our own handler using the \u003Ccode>os\u002Fsignal\u003C\u002Fcode> package. This is what we will use to implement our graceful shutdown.\u003C\u002Fp>\n\u003Ch3>Option 1: Using Channels\u003C\u002Fh3>\n\u003Cp>The first approach is to use a channel that receives signals:\u003C\u002Fp>\n\u003Cfigure data-rehype-pretty-code-figure=\"\">\u003Cpre tabindex=\"0\" data-language=\"go\" data-theme=\"vesper github-light\">\u003Ccode data-language=\"go\" data-theme=\"vesper github-light\" style=\"display: grid;\">\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">package\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> main\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> (\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">fmt\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">os\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">os\u002Fsignal\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">syscall\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> main\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tsignalChan \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> make\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">chan\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> os\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Signal\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#005CC5\">1\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tsignal.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Notify\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(signalChan, syscall.SIGINT, syscall.SIGTERM)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#8B8B8B94;--shiki-light:#6A737D\">\t\u002F\u002F normal cooking here (server setup, etc...)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t&#x3C;-\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">signalChan\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tfmt.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Println\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Received, shutting down...\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Ffigure>\n\u003Cp>We use a buffered channel with a capacity of 1 here to prevent blocking. \u003Ccode>signal.Notify\u003C\u002Fcode> tells Go to relay SIGINT and SIGTERM to our channel instead of using the default behavior. The \u003Ccode>&#x3C;-signalChan\u003C\u002Fcode> line blocks until a signal is received.\u003C\u002Fp>\n\u003Ch3>Option 2: Using Context (the Preferred Approach)\u003C\u002Fh3>\n\u003Cp>Starting with Go 1.16, you can simplify signal handling by using \u003Ccode>signal.NotifyContext\u003C\u002Fcode>, which ties signal handling directly to context cancellation:\u003C\u002Fp>\n\u003Cfigure data-rehype-pretty-code-figure=\"\">\u003Cpre tabindex=\"0\" data-language=\"go\" data-theme=\"vesper github-light\">\u003Ccode data-language=\"go\" data-theme=\"vesper github-light\" style=\"display: grid;\">\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">ctx, stop \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> signal.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">NotifyContext\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Background\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(), syscall.SIGINT, syscall.SIGTERM)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">defer\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> stop\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Ffigure>\n\u003Cp>\u003Ccode>NotifyContext\u003C\u002Fcode> returns a copy of the parent context that automatically cancels itself whenever one of the specified signals is received. This is the preferred approach because contexts are already deeply integrated into Go's standard library, and it lets us propagate the shutdown signal to all parts of our application naturally.\u003C\u002Fp>\n\u003Ch2>Building the Graceful Shutdown\u003C\u002Fh2>\n\u003Cp>Now that we have found a way to intercept shutdown signals, let's build the actual implementation. There are a few things we need to handle before we can wire it together.\u003C\u002Fp>\n\u003Ch3>Don't Drop Traffic During the Transition\u003C\u002Fh3>\n\u003Cp>This is something a lot of people miss. In a containerized environment (and many other orchestrated environments with external load balancers), you should not stop accepting new requests immediately. Even after a container is marked for shutdown or a pod is marked for termination, it might still receive traffic for a few moments before the load balancer pings again to know that it is inactive.\u003C\u002Fp>\n\u003Cp>To avoid connection errors during this short window, the correct approach is to fail the health check first. This tells the load balancer to stop sending you traffic:\u003C\u002Fp>\n\u003Cfigure data-rehype-pretty-code-figure=\"\">\u003Cpre tabindex=\"0\" data-language=\"go\" data-theme=\"vesper github-light\">\u003Ccode data-language=\"go\" data-theme=\"vesper github-light\" style=\"display: grid;\">\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">var\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> isShuttingDown \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">atomic\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Bool\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">http.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">HandleFunc\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u002Fhealth\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">w\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">ResponseWriter\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">r\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Request\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">    if\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> isShuttingDown.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Load\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">        http.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Error\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(w, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Shutting down\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, http.StatusServiceUnavailable)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">        return\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">    w.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">WriteHeader\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(http.StatusOK)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">    w.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Write\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">([]\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">byte\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"OK\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">))\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">})\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Ffigure>\n\u003Cp>After updating our availability status, we wait a small interval for the next health check ping from the load balancer. This gives it time to notice we are no longer healthy and stop routing new requests to us.\u003C\u002Fp>\n\u003Ch3>Shutting Down the Server and Notifying Handlers\u003C\u002Fh3>\n\u003Cp>Once the load balancer knows to leave us alone, we can actually shut down the server. With \u003Ccode>net\u002Fhttp\u003C\u002Fcode>, we do this by calling \u003Ccode>http.Server.Shutdown\u003C\u002Fcode>. This method stops the server from accepting new connections and waits for all active requests to complete before shutting down.\u003C\u002Fp>\n\u003Cp>It returns in only two situations:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Good case\u003C\u002Fstrong>: All active connections are closed and all handlers have finished processing.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\"Oof\"(Bad) case\u003C\u002Fstrong>: The context passed to \u003Ccode>Shutdown(ctx)\u003C\u002Fcode> expires before the handlers finish. In this case, the server gives up waiting and returns an error.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>But there is a problem. Handlers are not automatically aware when the server is shutting down. If a handler is doing a long-running operation (like a big database query or a slow external API call), it has no way of knowing it should wrap things up.\u003C\u002Fp>\n\u003Cp>We can solve this by setting the server's \u003Ccode>BaseContext\u003C\u002Fcode> field. \u003Ccode>BaseContext\u003C\u002Fcode> lets us provide a custom context that gets shared across all incoming connections. If we make that context cancellable, we can cancel it during shutdown, and every handler will be able to detect that it's time to stop:\u003C\u002Fp>\n\u003Cfigure data-rehype-pretty-code-figure=\"\">\u003Cpre tabindex=\"0\" data-language=\"go\" data-theme=\"vesper github-light\">\u003Ccode data-language=\"go\" data-theme=\"vesper github-light\" style=\"display: grid;\">\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">outgoingContext, stopOutgoingContext \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">WithCancel\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Background\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">())\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">server \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> &#x26;\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Server\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">{\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">    Addr: \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\":8080\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">    BaseContext: \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">_\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> net\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Listener\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> outgoingContext\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">    },\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Ffigure>\n\u003Cp>Here, \u003Ccode>outgoingContext\u003C\u002Fcode> is our cancellable context, and we wire it into the server through \u003Ccode>BaseContext\u003C\u002Fcode>. Now every handler can check \u003Ccode>r.Context().Done()\u003C\u002Fcode> to see if the server is shutting down, and exit early if needed.\u003C\u002Fp>\n\u003Ch3>The Full Implementation\u003C\u002Fh3>\n\u003Cp>Here is the full implementation with all the pieces connected:\u003C\u002Fp>\n\u003Cfigure data-rehype-pretty-code-figure=\"\">\u003Cpre tabindex=\"0\" data-language=\"go\" data-theme=\"vesper github-light\">\u003Ccode data-language=\"go\" data-theme=\"vesper github-light\" style=\"display: grid;\">\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">package\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> main\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> (\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">log\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">net\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">net\u002Fhttp\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">os\u002Fsignal\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">sync\u002Fatomic\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">syscall\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\t\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">time\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">var\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> isShuttingDown \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">atomic\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Bool\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> main\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tsignalContext, stopSignalContext \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> signal.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">NotifyContext\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Background\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(), syscall.SIGINT, syscall.SIGTERM)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\tdefer\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> stopSignalContext\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\thttp.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">HandleFunc\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u002Fhealth\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">w\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">ResponseWriter\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">r\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Request\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t\tif\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> isShuttingDown.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Load\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t\thttp.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Error\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(w, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Shutting down\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, http.StatusServiceUnavailable)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t\t\treturn\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\tw.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">WriteHeader\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(http.StatusOK)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\tw.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Write\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">([]\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">byte\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"OK\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">))\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t})\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\thttp.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">HandleFunc\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"\u002F\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">w\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">ResponseWriter\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">r\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Request\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t\tselect\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t\tcase\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> &#x3C;-\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">time.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">After\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#005CC5\">2\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> time.Second):\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t\tw.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">WriteHeader\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(http.StatusOK)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t\tw.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Write\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">([]\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">byte\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Aktiv!\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">))\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t\tcase\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> &#x3C;-\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">r.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">().\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Done\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">():\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t\thttp.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Error\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(w, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Request cancelled.\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, http.StatusRequestTimeout)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t})\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\toutgoingContext, stopOutgoingContext \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">WithCancel\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Background\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">())\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tserver \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> &#x26;\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">http\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Server\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">{\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\tAddr: \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\":8080\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\tBaseContext: \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">_\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> net\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Listener\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t\t\treturn\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> outgoingContext\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t},\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\tgo\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\tlog.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Println\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Server running on http:\u002F\u002Flocalhost:8080\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t\tif\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> err \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> server.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">ListenAndServe\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(); err \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">!=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#005CC5\"> nil\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> &#x26;&#x26;\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> err \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">!=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> http.ErrServerClosed {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">\t\t\tpanic\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(err)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\t}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t}()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\t&#x3C;-\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">signalContext.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Done\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">\tstopSignalContext\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tisShuttingDown.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Store\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#005CC5\">true\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tlog.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Println\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"shutdown signal received, shutting down...\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\ttime.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Sleep\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#005CC5\">5\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> time.Second)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tlog.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Println\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Health check propagated, waiting for ongoing requests to finish.\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tshutdownContext, cancelShutdownContext \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">WithTimeout\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(context.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Background\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(), \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#005CC5\">15\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">*\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">time.Second)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\tdefer\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> cancelShutdownContext\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\terr \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">:=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> server.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Shutdown\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(shutdownContext)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">\tif\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> err \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">!=\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#005CC5\"> nil\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\tlog.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Println\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Shutdown timed out, cancelling in-flight requests.\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">\t\tstopOutgoingContext\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\ttime.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Sleep\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#005CC5\">3\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> time.Second)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t\tserver.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Close\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\t}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">\tlog.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Println\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#99FFE4;--shiki-light:#032F62\">\"Server shut down gracefully.\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\"> \u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Ffigure>\n\u003Cp>Let me walk through the shutdown sequence so you can see how all the pieces work together:\u003C\u002Fp>\n\u003Col>\n\u003Cli>A SIGINT or SIGTERM arrives. \u003Ccode>signalContext\u003C\u002Fcode> gets cancelled, and the \u003Ccode>&#x3C;-signalContext.Done()\u003C\u002Fcode> line unblocks.\u003C\u002Fli>\n\u003Cli>We set \u003Ccode>isShuttingDown\u003C\u002Fcode> to true, so the \u003Ccode>\u002Fhealth\u003C\u002Fcode> endpoint starts returning \u003Ccode>503 Service Unavailable\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>We wait 5 seconds. This gives the load balancer time to notice the failed health check and stop sending us new traffic.\u003C\u002Fli>\n\u003Cli>We call \u003Ccode>server.Shutdown()\u003C\u002Fcode> with a 15-second timeout. This stops the server from accepting new connections and waits for all in-flight requests to finish.\u003C\u002Fli>\n\u003Cli>If requests complete within the timeout, we are done. If they don't, we cancel \u003Ccode>outgoingContext\u003C\u002Fcode> to signal all handlers to stop, wait a bit, and then force-close the server.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>A Note on time.Sleep vs time.After\u003C\u002Fh3>\n\u003Cp>If you noticed, the root handler uses \u003Ccode>time.After\u003C\u002Fcode> inside a \u003Ccode>select\u003C\u002Fcode> instead of a plain \u003Ccode>time.Sleep\u003C\u002Fcode>. This is intentional. \u003Ccode>time.Sleep\u003C\u002Fcode> blocks the goroutine unconditionally, so it will not respond to context cancellation. That completely defeats the purpose of what we are trying to achieve with the \u003Ccode>BaseContext\u003C\u002Fcode>. The handler would just sit there sleeping even though the server is trying to shut down.\u003C\u002Fp>\n\u003Cp>Instead, we can use a \u003Ccode>select\u003C\u002Fcode> that listens to both the timer and the context. You can use this helper function for context-aware sleeping:\u003C\u002Fp>\n\u003Cfigure data-rehype-pretty-code-figure=\"\">\u003Cpre tabindex=\"0\" data-language=\"go\" data-theme=\"vesper github-light\">\u003Ccode data-language=\"go\" data-theme=\"vesper github-light\" style=\"display: grid;\">\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">func\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> Sleep\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">ctx\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Context\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#E36209\">duration\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\"> time\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Duration\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">error\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">    select\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">    case\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> &#x3C;-\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">time.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">After\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">(duration):\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#005CC5\"> nil\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">    case\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\"> &#x3C;-\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">ctx.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Done\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">():\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#A0A0A0;--shiki-light:#D73A49\">        return\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\"> ctx.\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFC799;--shiki-light:#6F42C1\">Err\u003C\u002Fspan>\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan data-line=\"\">\u003Cspan style=\"--shiki-dark:#FFF;--shiki-light:#24292E\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Ffigure>\n\u003Cp>This way, if the context gets cancelled while we are waiting, we return immediately instead of blocking until the full duration elapses.\u003C\u002Fp>\n\u003Ch2>Demo\u003C\u002Fh2>\n\u003Cp>Here is a video showing the graceful shutdown in action:\u003C\u002Fp>\n\u003Cp>\u003Cvideo src=\"https:\u002F\u002Fres.cloudinary.com\u002Fdb6nohcui\u002Fvideo\u002Fupload\u002Fv1783633009\u002Fgraceful-shutdown-demo_ypp9sd.mp4\" controls playsinline width=\"100%\">\u003C\u002Fvideo>\u003C\u002Fp>\n\u003Ch2>Conclusion\u003C\u002Fh2>\n\u003Cp>From the implementation above, the server shuts down gracefully, handling in-flight requests properly and releasing resources. The key takeaways are:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Intercept signals\u003C\u002Fstrong> using \u003Ccode>signal.NotifyContext\u003C\u002Fcode> so you control what happens when your app receives a SIGTERM or SIGINT.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Fail the health check first\u003C\u002Fstrong> before stopping the server. This gives your load balancer time to stop routing new traffic to you.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Use \u003Ccode>server.Shutdown()\u003C\u002Fcode>\u003C\u002Fstrong> to let in-flight requests complete before closing.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Set a \u003Ccode>BaseContext\u003C\u002Fcode>\u003C\u002Fstrong> so your handlers can detect the shutdown and exit early if needed.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Use context-aware sleep\u003C\u002Fstrong> instead of \u003Ccode>time.Sleep\u003C\u002Fcode> in handlers, otherwise your graceful shutdown is not actually graceful.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>These patterns apply to any Go HTTP server, whether you are running on bare metal, in Docker, or on Kubernetes. The specifics of the timeouts will depend on your setup (how often your load balancer health checks, how long your longest request takes), but the structure stays the same.\u003C\u002Fp>\n\u003Cp>(If you want to see the full codebase, check the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fumohsamuel\u002Fgraceful-shutdown\">repository\u003C\u002Fa>. Play around with it and lmk what you think)\u003C\u002Fp>","July 9, 2026","2026-07-09T21:56:33.273Z","2026-07-09T22:18:52.438Z"]