npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@quanticjs/health

v8.1.0

Published

Health check module — liveness, readiness, startup probes with auto-detection, caching, and multiple transports

Readme

@quanticjs/health

Health check module for QuanticJS applications. Provides liveness, readiness, and startup probes with auto-detection, caching, and multiple transports for both HTTP and non-HTTP apps.

Installation

Already included in the @quanticjs/quanticjs umbrella. For standalone use:

npm install @quanticjs/health

Quick Start

HTTP API (most common)

import { Module } from '@nestjs/common';
import { QuanticCoreModule } from '@quanticjs/core';
import { QuanticHealthModule } from '@quanticjs/health';

@Module({
  imports: [
    QuanticCoreModule.forRoot(),
    QuanticHealthModule.forRoot({
      transport: { type: 'controller' },
    }),
  ],
})
export class AppModule {}

This registers three endpoints on your existing NestJS server:

| Endpoint | Probe | Purpose | |----------|-------|---------| | GET /health/live | Liveness | Is the process alive? Restart if not. | | GET /health/ready | Readiness | Can this instance serve traffic? Remove from LB if not. | | GET /health/startup | Startup | Has the app finished initializing? |

All endpoints are public (no auth required) and return:

{
  "status": "ok",
  "checks": {
    "database": { "status": "ok", "latency_ms": 2 },
    "redis": { "status": "ok", "latency_ms": 1 }
  },
  "timestamp": "2026-05-18T10:32:01.123Z"
}

Status code is 200 when all checks pass, 503 when any check fails.

Auto-Detection

When autoDetect is enabled (the default), the module scans the NestJS DI container on startup and registers checks automatically:

| Dependency | Detection | Probe | Check | |------------|-----------|-------|-------| | TypeORM DataSource | typeorm installed + DataSource in DI | readiness | SELECT 1 | | Redis (REDIS_CLIENT) | QuanticRedisModule imported | readiness | redis.ping() | | Event loop | Always | liveness | setImmediate responsiveness |

No configuration needed for framework-managed dependencies. The module logs what it discovers:

[HealthRegistry] Auto-detected DataSource → database readiness check
[HealthRegistry] Auto-detected Redis → redis readiness check
[HealthRegistry] readiness: [database, redis]
[HealthRegistry] liveness: [event_loop]

Disable with autoDetect: false.

Custom Checks

Add product-specific checks for dependencies the framework doesn't know about.

Function checks

QuanticHealthModule.forRoot({
  transport: { type: 'controller' },
  readiness: [
    {
      name: 'minio',
      check: async () => {
        const exists = await minioClient.bucketExists('my-bucket');
        if (!exists) throw new Error('Bucket not found');
      },
      timeoutMs: 5000, // optional, default 3000
    },
  ],
  startup: [
    {
      name: 'migrations',
      check: async () => {
        if (!migrationService.isComplete()) throw new Error('Migrations pending');
      },
    },
  ],
})

The check function should resolve when healthy and throw when unhealthy.

HTTP checks

For external services, pass a url instead of a check function:

QuanticHealthModule.forRoot({
  transport: { type: 'controller' },
  readiness: [
    { name: 'ai-gateway', url: 'http://ai-gateway:3005/health' },
    { name: 'kogito', url: 'http://kogito:8080/q/health/live', timeoutMs: 5000 },
  ],
})

HTTP checks expect a 2xx response. Any other status or network error marks the check as unhealthy.

Transports

The transport determines how probes reach the app.

controller — HTTP API apps

Mounts on the existing NestJS HTTP server. Endpoints: /health/live, /health/ready, /health/startup.

QuanticHealthModule.forRoot({
  transport: { type: 'controller' },
})

standalone — Workers, consumers, queue processors

Spins up a minimal HTTP server on a separate port. No NestJS overhead — just raw http.createServer.

QuanticHealthModule.forRoot({
  transport: { type: 'standalone', port: 9091 },
})

Endpoints: /live, /ready, /startup (no /health prefix since this is a dedicated health server).

Use this for apps that have no HTTP server but still need K8s/Docker health probes.

file — Cron jobs, one-shot migration scripts

Writes a JSON file when healthy, deletes it when unhealthy. Probes check file existence.

QuanticHealthModule.forRoot({
  transport: {
    type: 'file',
    path: '/tmp/.healthy',    // optional, default '/tmp/.healthy'
    intervalMs: 10000,        // optional, default 10000
  },
})

Docker healthcheck: test: ["CMD", "test", "-f", "/tmp/.healthy"]

none — Programmatic only

No endpoints, no files. Inject HealthRegistry directly for custom usage:

@Injectable()
export class MyService {
  constructor(private readonly health: HealthRegistry) {}

  async checkDeps() {
    const report = await this.health.evaluate('readiness');
    if (report.status === 'error') {
      // handle unhealthy state
    }
  }
}

Result Caching

By default, check results are cached for 5 seconds to avoid hammering dependencies on high-frequency probe intervals.

QuanticHealthModule.forRoot({
  transport: { type: 'controller' },
  cacheTtlMs: 10000, // cache for 10s
})

Set to 0 to disable caching (every probe hit runs all checks).

Shutdown Integration

When the app receives SIGTERM, the module:

  1. Flips readiness to 503 immediately (before GracefulShutdownService runs)
  2. Waits shutdownDelayMs (default 5s) for the load balancer to observe the change
  3. Then GracefulShutdownService proceeds with its drain + cleanup
{
  "status": "error",
  "reason": "shutting_down",
  "checks": {},
  "timestamp": "2026-05-18T10:35:00.000Z"
}

This ensures no new traffic arrives while the app is draining in-flight work.

QuanticHealthModule.forRoot({
  transport: { type: 'controller' },
  shutdownAware: true,      // default true
  shutdownDelayMs: 5000,    // default 5000
})

Disable with shutdownAware: false if you don't need this behavior.

Docker Compose

backend:
  healthcheck:
    test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000/health/ready"]
    interval: 10s
    timeout: 5s
    retries: 3
    start_period: 30s

worker:
  healthcheck:
    test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:9091/ready"]
    interval: 10s
    timeout: 5s
    retries: 3
    start_period: 15s

migration-job:
  healthcheck:
    test: ["CMD", "test", "-f", "/tmp/.healthy"]
    interval: 5s
    retries: 3

Kubernetes

# HTTP API
spec:
  containers:
    - name: backend
      livenessProbe:
        httpGet:
          path: /health/live
          port: 3000
        periodSeconds: 10
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /health/ready
          port: 3000
        periodSeconds: 10
        failureThreshold: 3
      startupProbe:
        httpGet:
          path: /health/startup
          port: 3000
        periodSeconds: 5
        failureThreshold: 30

---
# Worker (standalone transport)
spec:
  containers:
    - name: worker
      livenessProbe:
        httpGet:
          path: /live
          port: 9091
      readinessProbe:
        httpGet:
          path: /ready
          port: 9091

Registering Checks Programmatically

Inject HealthRegistry to register checks at runtime:

@Injectable()
export class KafkaConsumer implements OnModuleInit {
  constructor(private readonly health: HealthRegistry) {}

  onModuleInit() {
    this.health.register('readiness', 'kafka', async () => {
      if (!this.consumer.isConnected()) throw new Error('Kafka disconnected');
    });
  }
}

Full Options Reference

interface HealthModuleOptions {
  transport: HealthTransport;
  autoDetect?: boolean;          // default: true
  cacheTtlMs?: number;           // default: 5000
  shutdownAware?: boolean;       // default: true
  shutdownDelayMs?: number;      // default: 5000
  readiness?: HealthCheckConfig[];
  startup?: HealthCheckConfig[];
  liveness?: HealthCheckConfig[];
}

// Custom function check
interface CustomHealthCheck {
  name: string;
  check: () => Promise<void>;   // resolve = healthy, throw = unhealthy
  timeoutMs?: number;            // default: 3000
}

// HTTP endpoint check
interface HttpHealthCheck {
  name: string;
  url: string;
  timeoutMs?: number;            // default: 3000
}

type HealthTransport =
  | { type: 'controller' }
  | { type: 'standalone'; port: number }
  | { type: 'file'; path?: string; intervalMs?: number }
  | { type: 'none' };

Complete Example (AutoFlux-style)

import { Module } from '@nestjs/common';
import { QuanticCoreModule } from '@quanticjs/core';
import { QuanticRedisModule } from '@quanticjs/redis';
import { QuanticHealthModule } from '@quanticjs/health';

@Module({
  imports: [
    QuanticCoreModule.forRoot(),
    QuanticRedisModule.forRoot(),
    // TypeOrmModule.forRoot({ ... }),

    QuanticHealthModule.forRoot({
      transport: { type: 'controller' },

      // Auto-detects: database (TypeORM), redis, event_loop
      // Add product-specific checks below:

      readiness: [
        { name: 'minio', check: async () => {
          const exists = await minioClient.bucketExists('autoflux');
          if (!exists) throw new Error('Bucket missing');
        }},
        { name: 'ai-gateway', url: 'http://ai-gateway:3005/health' },
        { name: 'kogito', url: 'http://kogito:8080/q/health/live', timeoutMs: 5000 },
      ],

      startup: [
        { name: 'templates-seeded', check: async () => {
          if (!seederService.isComplete()) throw new Error('Seeding in progress');
        }},
      ],

      cacheTtlMs: 5000,
      shutdownDelayMs: 5000,
    }),
  ],
})
export class AppModule {}