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

@unidev-hub/health

v1.1.24

Published

Standardized health checks for TypeScript services with readiness/liveness probes, dependency monitoring, and dashboard visualization

Readme

@unidev-hub/health

A standardized health check system for TypeScript/Node.js services with support for readiness/liveness probes, dependency health reporting, customizable health indicators, and metrics reporting.

npm version License: MIT TypeScript

Features

  • TypeScript-first design: Full type safety with comprehensive TypeScript definitions
  • Standardized health check endpoints: Easily implement Kubernetes-compatible liveness and readiness probes
  • Dependency health monitoring: Track the health of HTTP endpoints, databases, and other service dependencies
  • Customizable health indicators: Create custom health checks to monitor any aspect of your service
  • Health status aggregation: Automatically determine overall service health based on individual components
  • Performance metrics: Track response times and resource usage
  • Cached responses: Configurable caching to reduce the performance impact of frequent health checks
  • Express integration: Simple middleware for adding health endpoints to Express applications

Installation

npm install @unidev-hub/health

Quick Start

import express from 'express';
import { 
  HealthService, 
  MemoryHealthIndicator,
  HttpHealthIndicator,
  createHealthEndpoint 
} from '@unidev-hub/health';

// Create health service
const healthService = new HealthService();

// Add memory indicator to monitor heap usage
healthService.addIndicator(new MemoryHealthIndicator({
  thresholdPercent: 85 // Alert when heap usage exceeds 85%
}));

// Add HTTP dependency indicator to check external API
healthService.addIndicator(new HttpHealthIndicator({
  name: 'payment-api',
  url: 'https://api.payment-provider.com/status',
  timeout: 3000,
  expectedStatus: 200
}));

// Create Express app and add health endpoints
const app = express();
app.use(createHealthEndpoint(healthService));

// Start server
app.listen(3000, () => {
  console.log('Server running with health checks at:');
  console.log('- /health            (Basic health check)');
  console.log('- /health/liveness   (Liveness probe)');
  console.log('- /health/readiness  (Readiness probe)');
  console.log('- /health/details    (Detailed health report)');
});

Health Endpoints

The module provides four standard health check endpoints:

  • /health: Basic health status with minimal details
  • /health/liveness: Kubernetes liveness probe (is the service running?)
  • /health/readiness: Kubernetes readiness probe (is the service ready to receive traffic?)
  • /health/details: Detailed health report with all component statuses

Built-in Health Indicators

Memory Health Indicator

Monitors memory usage of the Node.js process.

import { MemoryHealthIndicator } from '@unidev-hub/health';

const memoryIndicator = new MemoryHealthIndicator({
  thresholdPercent: 90 // Optional: threshold for DEGRADED status (default: 90%)
});

healthService.addIndicator(memoryIndicator);

Disk Health Indicator

Monitors available disk space.

import { DiskHealthIndicator } from '@unidev-hub/health';

const diskIndicator = new DiskHealthIndicator({
  path: '/', // Optional: path to monitor (default: '/')
  thresholdPercent: 90 // Optional: threshold for DEGRADED status (default: 90%)
});

healthService.addIndicator(diskIndicator);

HTTP Health Indicator

Monitors the health of HTTP dependencies.

import { HttpHealthIndicator } from '@unidev-hub/health';

const apiIndicator = new HttpHealthIndicator({
  name: 'auth-service', // Optional: name for the indicator
  url: 'https://auth.example.com/health',
  method: 'GET', // Optional: HTTP method (default: 'GET')
  timeout: 5000, // Optional: timeout in ms (default: 5000)
  expectedStatus: 200, // Optional: expected HTTP status (default: 200)
  headers: { 'Authorization': 'Bearer token' } // Optional: custom headers
});

healthService.addIndicator(apiIndicator);

Database Health Indicator

Monitors database connectivity.

import { DatabaseHealthIndicator, DatabaseConnection } from '@unidev-hub/health';

// Your database connection object implementing the DatabaseConnection interface
const db: DatabaseConnection = {
  async query(sql: string) {
    // Your database query implementation
    return someDbClient.query(sql);
  },
  config: {
    database: 'users',
    host: 'localhost'
  }
};

const dbIndicator = new DatabaseHealthIndicator({
  name: 'primary-db', // Optional: name for the indicator
  connection: db, // Required: database connection object
  validationQuery: 'SELECT 1', // Optional: query to validate connection (default: 'SELECT 1')
  timeout: 3000 // Optional: timeout in ms (default: 5000)
});

healthService.addIndicator(dbIndicator);

Custom Health Indicators

You can create custom health indicators to monitor any aspect of your application:

Using the Factory Function

import { createHealthIndicator, Status, HealthResult } from '@unidev-hub/health';

// Example Redis client
interface RedisClient {
  ping(): Promise<string>;
  options: {
    host: string;
    port: number;
  };
}

const redisClient: RedisClient = {
  /* your Redis client */
};

const RedisHealthIndicator = createHealthIndicator('redis', async (): Promise<HealthResult> => {
  try {
    const start = Date.now();
    await redisClient.ping();
    const responseTime = Date.now() - start;
    
    return {
      status: Status.UP,
      details: {
        responseTime: `${responseTime}ms`,
        host: redisClient.options.host
      }
    };
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error);
    return {
      status: Status.DOWN,
      details: { error: errorMessage }
    };
  }
});

// Create an instance of the indicator
healthService.addIndicator(new RedisHealthIndicator());

Extending the Base Class

import { HealthIndicator, Status, HealthResult } from '@unidev-hub/health';

// Example message queue client
interface QueueClient {
  getStats(): Promise<{
    messageCount: number;
    consumerCount: number;
    oldestMessage: string;
  }>;
}

class QueueHealthIndicator extends HealthIndicator {
  private queueClient: QueueClient;

  constructor(queueClient: QueueClient) {
    super('message-queue');
    this.queueClient = queueClient;
  }

  async check(): Promise<HealthResult> {
    try {
      const stats = await this.queueClient.getStats();
      const status = stats.consumerCount > 0 ? Status.UP : Status.DEGRADED;
      
      return {
        status,
        details: {
          messageCount: stats.messageCount,
          consumerCount: stats.consumerCount,
          oldestMessage: stats.oldestMessage
        }
      };
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      return {
        status: Status.DOWN,
        details: { error: errorMessage }
      };
    }
  }
}

const mqClient: QueueClient = {
  /* your message queue client */
};

healthService.addIndicator(new QueueHealthIndicator(mqClient));

Health Service Configuration

Caching Results

For performance reasons, health check results are cached by default for 10 seconds:

// Change cache time to 30 seconds
healthService.setCacheTime(30000);

// Force a fresh health check
const healthStatus = await healthService.check(false);

Checking Health Programmatically

You can check the health of your service programmatically:

// Get the current health status
const healthStatus = await healthService.check();

// Log overall status
console.log(`Service status: ${healthStatus.status}`);

// Check a specific component
if (healthStatus.components.database.status === Status.DOWN) {
  console.error('Database is down:', healthStatus.components.database.details);
}

Express Middleware Configuration

You can customize the health endpoint paths:

import { createHealthEndpoint } from '@unidev-hub/health';

const healthMiddleware = createHealthEndpoint(healthService, {
  path: '/status', // Basic health endpoint
  livenessPath: '/status/alive', // Liveness probe
  readinessPath: '/status/ready', // Readiness probe
  detailedPath: '/status/details' // Detailed health report
});

app.use(healthMiddleware);

Health Status Response Format

Basic Health Endpoint Response

{
  "status": "UP",
  "timestamp": "2025-03-14T15:30:45.123Z",
  "metrics": {
    "responseTime": "12ms",
    "componentCount": 3
  }
}

Detailed Health Endpoint Response

{
  "status": "DEGRADED",
  "timestamp": "2025-03-14T15:30:45.123Z",
  "components": {
    "memory": {
      "status": "UP",
      "details": {
        "total": "512 MB",
        "used": "128 MB",
        "free": "384 MB",
        "percentage": "25.00%"
      }
    },
    "payment-api": {
      "status": "DEGRADED",
      "details": {
        "url": "https://api.payment-provider.com/status",
        "statusCode": 200,
        "expectedStatus": 200,
        "responseTime": "2500ms"
      }
    },
    "database": {
      "status": "UP",
      "details": {
        "database": "users",
        "validationQuery": "SELECT 1",
        "responseTime": "5ms"
      }
    }
  },
  "metrics": {
    "responseTime": "2510ms",
    "componentCount": 3
  }
}

Status Codes

Health checks use four possible status values:

  • UP: Component is fully operational
  • DOWN: Component is not functioning and requires attention
  • DEGRADED: Component is functioning but with reduced performance or capabilities
  • UNKNOWN: Component status could not be determined

Integration with Kubernetes

This health check system is designed to work seamlessly with Kubernetes:

# Example Kubernetes deployment with probes
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service
spec:
  template:
    spec:
      containers:
      - name: my-service
        image: my-service:1.0.0
        ports:
        - containerPort: 3000
        livenessProbe:
          httpGet:
            path: /health/liveness
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health/readiness
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5

Best Practices

  1. Use TypeScript: Take advantage of the TypeScript definitions for type safety and better developer experience

  2. Meaningful Component Names: Use descriptive names for health indicators to easily identify issues

  3. Correct Status Usage:

    • UP: Component is fully operational
    • DOWN: Component is not functioning
    • DEGRADED: Component is working but with reduced performance
    • UNKNOWN: Status could not be determined
  4. Timeouts: Always set reasonable timeouts for dependency checks to avoid hanging health checks

  5. Error Handling: Always use try/catch blocks in custom health indicators to avoid crashing the health check system

  6. Security: Consider protecting your detailed health endpoint (/health/details) with authentication in production

Advanced Patterns

Critical vs. Non-Critical Components

You can implement a system to differentiate critical components:

import { HealthService, Status } from '@unidev-hub/health';

// Mark components as critical by extending HealthIndicator
class CriticalHealthIndicator extends HealthIndicator {
  readonly critical: boolean = true;
  // ...rest of implementation
}

// Or add a property to existing indicators
interface CriticalIndicator {
  critical?: boolean;
}

// Mark components as critical
function markAsCritical(healthService: HealthService, componentName: string): void {
  const indicators = healthService.getIndicators();
  const indicator = indicators.get(componentName) as HealthIndicator & CriticalIndicator;
  
  if (indicator) {
    indicator.critical = true;
  }
}

// Use this information in your health check processing
// ...

Custom Express Middleware with Critical Components

function createCustomHealthEndpoint(healthService: HealthService, options = {}) {
  const standardMiddleware = createHealthEndpoint(healthService, options);
  
  return function(req: Request, res: Response, next: NextFunction) {
    if (req.path === options.readinessPath || req.path === '/health/readiness') {
      // Check if any critical component is down
      healthService.check().then(result => {
        const indicators = healthService.getIndicators();
        
        let criticalDown = false;
        for (const [name, indicator] of indicators.entries()) {
          if ((indicator as any).critical && result.components[name].status === Status.DOWN) {
            criticalDown = true;
            break;
          }
        }
        
        if (criticalDown) {
          res.status(503).json({
            status: Status.DOWN,
            message: 'Critical component is down'
          });
        } else {
          // Continue with standard processing
          standardMiddleware(req, res, next);
        }
      }).catch(next);
    } else {
      standardMiddleware(req, res, next);
    }
  };
}

Running Tests

# Install dependencies
npm install

# Run tests
npm test

# Run linting
npm run lint

Example Applications

The package includes example applications that demonstrate how to use the health check system:

# Run the simple Express example
npm run example:simple

# Run the custom indicator example
npm run example:custom

FAQ

How do I test my custom health indicator?

You can test your custom health indicator using Jest:

import { Status } from '@unidev-hub/health';
import MyCustomHealthIndicator from './my-custom-health-indicator';

// Mock your dependencies
jest.mock('./my-dependency', () => ({
  checkStatus: jest.fn()
}));

describe('MyCustomHealthIndicator', () => {
  let indicator: MyCustomHealthIndicator;
  
  beforeEach(() => {
    indicator = new MyCustomHealthIndicator();
  });
  
  test('should return UP status when service is healthy', async () => {
    // Arrange
    const mockDependency = require('./my-dependency');
    mockDependency.checkStatus.mockResolvedValue({ healthy: true });
    
    // Act
    const result = await indicator.check();
    
    // Assert
    expect(result.status).toBe(Status.UP);
    expect(result.details).toHaveProperty('responseTime');
  });
  
  test('should return DOWN status when service is unhealthy', async () => {
    // Arrange
    const mockDependency = require('./my-dependency');
    mockDependency.checkStatus.mockRejectedValue(new Error('Connection failed'));
    
    // Act
    const result = await indicator.check();
    
    // Assert
    expect(result.status).toBe(Status.DOWN);
    expect(result.details).toHaveProperty('error', 'Connection failed');
  });
});

How do I register health checks with other frameworks?

While Express middleware is provided out of the box, you can use the HealthService directly with any web framework:

// Example with Fastify
import fastify from 'fastify';
import { HealthService } from '@unidev-hub/health';

const app = fastify();
const healthService = new HealthService();

// Add your indicators
// ...

// Register routes
app.get('/health', async (request, reply) => {
  const health = await healthService.check();
  const statusCode = health.status === 'UP' ? 200 : 
                     health.status === 'DEGRADED' ? 200 : 503;
  
  return reply.status(statusCode).send({
    status: health.status,
    timestamp: health.timestamp,
    metrics: health.metrics
  });
});

app.get('/health/details', async (request, reply) => {
  const health = await healthService.check();
  const statusCode = health.status === 'UP' ? 200 : 
                     health.status === 'DEGRADED' ? 200 : 503;
  
  return reply.status(statusCode).send(health);
});

// Start server
app.listen({ port: 3000 });

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.