DEV Community

Željko Šević
Željko Šević

Posted on • Originally published at sevic.dev on

6

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

Course

Build your SaaS in 2 weeks - Start Now

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more