Golang graceful shutdown

Last Updated Feb 20, 2023

Graceful shutdown refers to shutting down a server or service in a way that allows it to finish any outstanding requests or tasks before exiting. This helps ensure that users are not left with incomplete or inconsistent results.

Clients would receive errors whenever a container was shutting down on the server side if there was no appropriate graceful shutdown in place. In the worst situation, it might also result in data loss.

What we want is that when the service is forced to stop it will:

  1. Stop accept new requests.
  2. Continue process and responnse to old requests.
  3. Finally, close the connections, and the shutdown the service completely.

This example bellow sets up an HTTP server on port 6969 and waits for an interrupt signal (more on this later). When the signal is received, it cancels the context and waits for any outstanding requests or tasks to finish. Finally, it shuts down the server gracefully and exits.

func main() {
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, os.Interrupt)

	// start a web server in a goroutine
    srv := &http.Server{Addr: ":6969"}
    go func() {

    log.Println("beep boop.. signal received...")

	//  cancels the context
    // waits 3s for any outstanding requests or tasks to finish
    ctx, cancel := context.WithTimeout(context.Background(), 3 * time.Second)
    defer cancel()
    // clean up stuff
    err := server.Shutdown(ctx)
    if err != nil {
        log.Fatalf("oops! failed: %s", err)
    // release other resources, 
    // such as database connections, redis.. etc here

    // finally
    log.Println("nice, server shut down gracefully.")


In computing, a signal is a software interrupt delivered to a process. Signals are used in many operating systems to notify a process of an event or condition that requires its attention, such as a request to terminate or a user interrupt. Signals are typically generated by the operating system or by another process, and are delivered to a process via a signal handler.

In Go, the "os/signal" package provides a way to handle signals. You can create a channel of type os.Signal, and use the signal.Notify function to listen for specific signals and send them to the channel.

There are many signals, but only shutdown signals are of interest to us. (syscall.SIGINT, syscall.SIGTERM).

So let's take a closer look at them:

SIGINT is a signal in computing that stands for "signal interrupt". It is a software interrupt that is sent to a process by the operating system when a user presses the "interrupt" key (usually Ctrl+C) in the terminal.

The purpose of SIGINT is to request that a process terminate gracefully. When a process receives a SIGINT signal, it is expected to perform any necessary cleanup actions and then exit. This allows users to stop a process that is running in the foreground by pressing Ctrl+C, rather than having to kill the process using the operating system's process management tools.

SIGTERM is a software interrupt that is sent to a process by the operating system to request that it terminate gracefully.

Unlike the SIGINT signal, which is typically initiated by a user pressing the "interrupt" key (usually Ctrl+C) in the terminal, the SIGTERM signal is often initiated by an external process, such as a process manager or a script, to request that a process shut down gracefully.

Since, SIGINT and SIGTERM covers almost all scenarios, our graceful shutdown server should work as long as we catch and process the signals.


Graceful shutdown is one of many things that you need to implement to have a resilient & robust application. By gracefully shutting down programs and releasing resources, you can ensure that your programs exit cleanly and don't cause any problems or leave any resources open that could lead to issues later on. Or so I hope.

Thanks for reading and happy coding !

Others articles of me write about golang

If you like golang, here is some others articles of the same author (me) about golang topic. Check it out !

  1. Golang error handling
  2. Golang context best practices
  3. Golang composition over Inheritance all you need to know

Hi there. Nodeepshit is a hobby website built to provide free information. There are no chargers to use the website.

If you enjoy our tutorials and examples, please consider supporting us with a cup of beer, we'll use the funds to create additional excellent tutorials.

If you don't want or unable to make a small donation please don't worry - carry on reading and enjoying the website as we explore more tutorials. Have a wonderful day!