DEV Community

Cover image for Health checks with Terminus
Ž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

Need help with your project?

Get personalized advice on your architecture, code, or career in a 45-minute 1-on-1 consultation.

Book a consultation

Top comments (0)