Observability: Node js Health Check Example

08.21.2021

Intro

Building out health checks is a common task when building a web server. You may have seen status sites, such as Github status, where we can see the update time of each service that is offered. In this article, we will learn how to create a basic health check end point.

The first step to building out a feature like this could be a simple health route, then we can combine this with a metrics counter to log a time of up and down time. We could also add alerting for when our service goes down. In later articles, we will explore adding these features. Let's get started with a few basics.

Installing the Modules

For this project, we will simply build a basic http service and eventually we will connect to our DB to ensure the service is fully connected. To do this, install the following.

npm install express pg

A Basic Health Endpoint

Let's start by creating a simply endpoint called /health that we can ping. This endpoint will simply return a 200 status. If we don't get a 200 status, we can assume the server is down.

const express = require('express')

async function start() {
    const app = express()
    const port = 3000
    
    app.get('/health', (req, res) => {
        return res.status(200)
    })
    
    app.listen(port, () => {
        console.log(`Example app listening at http://localhost:${port}`)
    })
}

(async () => {
    await start()
})()

Checking the Health

Now, to ping the service, we can curl as such:

curl http://localhost:3000/health

In practice, we would most likely have a cron service that will ping this on an interval, log the result so we can view stats later, and send alerts if there is down time. In a later article, we will build this out.

Adding More to the Health Check

Let's add a little more details our health check. You can get as complex or as simple as you want here. The complexity will depend on what kind of health reports you want. For example, let's say we had a postgres database. To consider our service "healthy" we also want to confirm that we can query to database. Let's add the following:

const express = require('express')
const pg = require('pg')

const pgClient = new pg.Client()
pgClient.connect()

async function start() {
    const app = express()
    const port = 3000
    
    app.get('/health', (req, res) => {
        try {
            await pg.query('SELECT $1::text as status', ['ACK']);
        } catch(e) {
            return res.status(200).json({
                message: 'Database down',
            })
        }

        return res.status(200)
    })
    
    app.listen(port, () => {
        console.log(`Example app listening at http://localhost:${port}`)
    })
}

(async () => {
    await start()
})()