---
id: 69f3046f4c0e76cbdd248590
title: How do Health Checks and Graceful Shutdowns Work in Express?
challengeType: 19
dashedName: how-do-health-checks-and-graceful-shutdowns-work-in-express
---

# --description--

Ever wondered how to keep your Express app stable and production-ready, especially when it's under heavy load or shutting down?

That's where health checks and graceful shutdowns come in. These two patterns help you keep your app available, and ensure it exits cleanly without dropping requests or corrupting data.

Let's break it down.

First, what even is a "health check" in Express?

A health check is a simple route that tells whether your app is up and running.

For example:

```js
app.get('/health', (req, res) => {
  res.status(200).send('OK')
})
```

Tools like load balancers or container orchestrators - think Kubernetes or AWS Elastic Beanstalk - can ping this route to decide if your app is healthy.

If the route returns a 200 status code, your service is considered healthy. As a reminder - a 200 HTTP status code means everything is okay!

If it doesn't respond, the orchestrator can restart the service automatically.

And what is a "graceful shutdown"?

A graceful shutdown is what happens when your app is about to stop, like when a server is restarting or a deployment is happening.

Instead of cutting off connections immediately, you give the app time to finish what it's doing.

In Express, you can listen for `SIGTERM`, which is a system signal sent when a process should terminate.

Here's an example:

```js
process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Server closed. Cleaning up...')
    // Close DB connections or other cleanup here
  })
})
```

This tells Express to stop accepting new connections and wait for existing ones to finish before exiting.

You should also handle `SIGINT`, which is the signal sent when you press Ctrl+C to stop your app during local development.

While `SIGTERM` is typically used by orchestrators like Kubernetes in production, `SIGINT` covers the everyday developer workflow. Without handling it, hitting Ctrl+C kills the process immediately, skipping any cleanup you've set up.

Since both signals should trigger the same graceful shutdown behavior, developers commonly listen for both.

Now, lets put it all together

Imagine your app is running in a container. Kubernetes sends a `SIGTERM` to shut it down for an update.

With just a basic graceful shutdown, your app stops accepting new connections and finishes up current requests. Once all work is done, it disconnects from the database and exits cleanly. No lost data, no corrupted state.

But there's a problem — the load balancer doesn't know your app is shutting down, so it might keep sending new traffic your way. That's where the bonus pattern below comes in.

Now, I have a little bonus for you. We will look at "Marking the App as Unhealthy Before Shutdown".

Before shutting down, you can update your health check to return a 503 status. That way, the load balancer sees the unhealthy response and stops routing new traffic to your app during the shutdown window, as demonstrated in the code above.

Reminder: A `503` status code means "Service Unavailable". it signals that the server is temporarily unable to handle requests, which is exactly what's happening during a graceful shutdown.

```js
let isShuttingDown = false

app.get('/health', (req, res) => {
  if (isShuttingDown) {
    res.status(500).send('Shutting down')
  } else {
    res.status(200).send('OK')
  }
})

process.on('SIGTERM', () => {
  isShuttingDown = true

  server.close(() => {
    console.log('Graceful shutdown complete')
    // Perform cleanup
  })
})
```

# --questions--

## --text--

What is the main purpose of a health check route?

## --answers--

To restart the server

### --feedback--

Think about how a load balancer knows if the app is up.

---

To report whether the app is running correctly.

---

To monitor user traffic.

### --feedback--

Think about how a load balancer knows if the app is up.

---

To log requests.

### --feedback--

Think about how a load balancer knows if the app is up.

## --video-solution--

2

## --text--

What does the `SIGTERM` signal do?

## --answers--

Starts the server.

### --feedback--

It happens during deployments or shutdowns.

---

Resets the app.

### --feedback--

It happens during deployments or shutdowns.

---

Tells the app to begin shutting down.

---

Sends debug information.

### --feedback--

It happens during deployments or shutdowns.

## --video-solution--

3

## --text--

Why would you send a 500 response from your health check during shutdown?

## --answers--

To cause an error.

### --feedback--

You want no new requests during shutdown.

---

To slow down requests.

### --feedback--

You want no new requests during shutdown.

---

To tell the load balancer to stop sending traffic.

---

To trigger garbage collection.

### --feedback--

You want no new requests during shutdown.
## --video-solution--

3
