DEV Community

Željko Šević
Željko Šević

Posted on • Originally published at sevic.dev on

Health checks with Terminus

Monitoring tools use health checks to check if service and external dependencies (like a database) are up and running and take some action (like sending alerts) for the unhealthy state.

Terminus provides a set of health indicators.

Liveness probe

An HTTP endpoint checks if the service is up and running.

// health.controller.ts
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import {
  HealthCheck,
  HealthCheckResult,
  HealthCheckService,
  HealthIndicatorResult,
  TypeOrmHealthIndicator
} from '@nestjs/terminus';
import { CustomConfigService } from 'common/config/custom-config.service';

@ApiTags('health')
@Controller('health')
export class HealthController {
  constructor(
    private readonly healthCheckService: HealthCheckService,
    private readonly configService: CustomConfigService,
    private readonly database: TypeOrmHealthIndicator
  ) {}

  @Get('liveness')
  @HealthCheck()
  async check(): Promise<HealthCheckResult> {
    return this.healthCheckService.check([
      async (): Promise<HealthIndicatorResult> => ({
        [this.configService.SERVICE_NAME]: { status: 'up' }
      })
    ]);
  }
  // ...
}
Enter fullscreen mode Exit fullscreen mode

A successful response is like the one below.

{
  "status": "ok",
  "info": {
    "nestjs-starter": {
      "status": "up"
    }
  },
  "error": {},
  "details": {
    "nestjs-starter": {
      "status": "up"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Readiness probe

An HTTP endpoint checks if the service is ready to receive the traffic and if all external dependencies are running.

// health.controller.ts
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import {
  HealthCheck,
  HealthCheckResult,
  HealthCheckService,
  HealthIndicatorResult,
  TypeOrmHealthIndicator
} from '@nestjs/terminus';
import { CustomConfigService } from 'common/config/custom-config.service';

@ApiTags('health')
@Controller('health')
export class HealthController {
  constructor(
    private readonly healthCheckService: HealthCheckService,
    private readonly configService: CustomConfigService,
    private readonly database: TypeOrmHealthIndicator
  ) {}

  // ...
  @Get('readiness')
  @HealthCheck()
  async checkReadiness(): Promise<HealthCheckResult> {
    return this.healthCheckService.check([
      async (): Promise<HealthIndicatorResult> =>
        this.database.pingCheck('postgres')
    ]);
  }
}
Enter fullscreen mode Exit fullscreen mode

Responses

  • Successful response
{
  "status": "ok",
  "info": {
    "postgres": {
      "status": "up"
    }
  },
  "error": {},
  "details": {
    "postgres": {
      "status": "up"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Response when the database is down
{
  "status": "error",
  "info": {},
  "error": {
    "postgres": {
      "status": "down"
    }
  },
  "details": {
    "postgres": {
      "status": "down"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Demo

The demo with the mentioned examples is available here.

Boilerplate

Here is the link to the boilerplate I use for the development.

Top comments (0)