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
HealthModulevia@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
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 {}
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() };
}
}
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 {}
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" }
}
}
When a check fails, HTTP status becomes 503 — Vigilmon catches this and alerts your team.
Step 6: Configure Vigilmon
- Create an account at vigilmon.online (free)
- Add Monitor → HTTP Monitor
- URL:
https://api.example.com/health/liveness - Check interval: 1 minute
- 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);
}
}
Or use the @Public() decorator pattern:
@Controller('health')
export class HealthController {
@Get('liveness')
@Public() // Mark as public (no auth required)
liveness() {
return { status: 'ok' };
}
}
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));
}
}
}
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' };
}
}
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.
Top comments (0)