DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Your NestJS Application with Vigilmon

How to Monitor Your NestJS Application with Vigilmon

NestJS is a structured, opinionated Node.js framework that makes it easy to build scalable server-side applications with TypeScript. It's widely used for enterprise APIs, microservices, and BFF (Backend for Frontend) layers. This guide shows you how to add production-grade uptime monitoring to NestJS with Vigilmon.

NestJS Monitoring Strategy

NestJS gives you some structure advantages:

  • Built-in HealthModule via @nestjs/terminus
  • Structured dependency injection makes health check integration clean
  • Guards can easily protect or expose health endpoints

Step 1: Install Terminus (NestJS Health Checks)

npm install @nestjs/terminus
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Health Module

// health/health.module.ts
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { HttpModule } from '@nestjs/axios';
import { HealthController } from './health.controller';

@Module({
  imports: [TerminusModule, HttpModule],
  controllers: [HealthController],
})
export class HealthModule {}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create a Health Controller

// health/health.controller.ts
import { Controller, Get } from '@nestjs/common';
import {
  HealthCheckService,
  HealthCheck,
  TypeOrmHealthIndicator,
  MemoryHealthIndicator,
} from '@nestjs/terminus';

@Controller('health')
export class HealthController {
  constructor(
    private health: HealthCheckService,
    private db: TypeOrmHealthIndicator,
    private memory: MemoryHealthIndicator,
  ) {}

  @Get()
  @HealthCheck()
  check() {
    return this.health.check([
      () => this.db.pingCheck('database'),
      () => this.memory.checkHeap('memory_heap', 200 * 1024 * 1024), // 200MB
    ]);
  }

  @Get('liveness')
  liveness() {
    return { status: 'ok', timestamp: new Date().toISOString() };
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Register the Health Module

// app.module.ts
import { Module } from '@nestjs/common';
import { HealthModule } from './health/health.module';

@Module({
  imports: [
    HealthModule,
    // ... other modules
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Now you have:

  • GET /health — full health check (DB + memory)
  • GET /health/liveness — simple liveness check

Step 5: Terminus Response Format

When all checks pass, Terminus returns:

{
  "status": "ok",
  "info": {
    "database": { "status": "up" },
    "memory_heap": { "status": "up" }
  },
  "error": {},
  "details": {
    "database": { "status": "up" },
    "memory_heap": { "status": "up" }
  }
}
Enter fullscreen mode Exit fullscreen mode

When a check fails, HTTP status becomes 503 — Vigilmon catches this and alerts your team.

Step 6: Configure Vigilmon

  1. Create an account at vigilmon.online (free)
  2. Add Monitor → HTTP Monitor
  3. URL: https://api.example.com/health/liveness
  4. Check interval: 1 minute
  5. Alert after: 2 consecutive failures

Add a second monitor for /health (full check) with a 5-minute interval.

Step 7: Exclude Health from Authentication

If your NestJS app uses JWT guards globally, exclude the health endpoint:

// app.module.ts or in your guard
import { APP_GUARD } from '@nestjs/core';
import { JwtAuthGuard } from './auth/jwt-auth.guard';

// In JwtAuthGuard:
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  canActivate(context: ExecutionContext) {
    const request = context.switchToHttp().getRequest();
    if (request.path.startsWith('/health')) {
      return true; // Skip auth for health checks
    }
    return super.canActivate(context);
  }
}
Enter fullscreen mode Exit fullscreen mode

Or use the @Public() decorator pattern:

@Controller('health')
export class HealthController {
  @Get('liveness')
  @Public() // Mark as public (no auth required)
  liveness() {
    return { status: 'ok' };
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 8: Custom Health Indicators

NestJS Terminus supports custom health indicators for any dependency:

import { Injectable } from '@nestjs/common';
import { HealthIndicator, HealthIndicatorResult, HealthCheckError } from '@nestjs/terminus';
import { InjectRedis } from '@liaoliaots/nestjs-redis';
import Redis from 'ioredis';

@Injectable()
export class RedisHealthIndicator extends HealthIndicator {
  constructor(@InjectRedis() private readonly redis: Redis) {
    super();
  }

  async isHealthy(key: string): Promise<HealthIndicatorResult> {
    try {
      await this.redis.ping();
      return this.getStatus(key, true);
    } catch (e) {
      throw new HealthCheckError('Redis check failed', this.getStatus(key, false));
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 9: NestJS Microservices

For NestJS microservices over TCP/gRPC:

// Expose an HTTP health endpoint even for non-HTTP microservices
@Controller('health')
export class HealthController {
  @Get()
  async check() {
    // Check that the microservice can process messages
    return { status: 'ok', service: 'user-service' };
  }
}
Enter fullscreen mode Exit fullscreen mode

Run a hybrid app that exposes both your TCP microservice and an HTTP health port.

Monitor Configuration for NestJS

Monitor Endpoint Interval When to Alert
Liveness /health/liveness 1 min 2 failures
Full health /health 5 min 1 failure
API root / 5 min 2 failures
SSL cert (auto) Daily 30 days out

Summary

NestJS with Terminus gives you structured health checks out of the box. Vigilmon gives you external verification from multiple regions — so you know when your app is actually reachable, not just when your in-process checks pass.

Start monitoring your NestJS app free on Vigilmon.

Top comments (0)