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

omni-db

v0.5.2

Published

Thin database orchestration library for Node.js - manage multiple connections with health monitoring and failover

Readme

OmniDB

Thin database orchestration library for Node.js — manage multiple connections with health monitoring and failover.

License: MIT Node.js Tests Coverage CI

Features

  • 🔌 Multi-Database Support — Bring your own clients (Prisma, Drizzle, Redis, MongoDB, etc.)
  • 🏥 Health Monitoring — Configurable periodic health checks with timeouts
  • 🔄 Automatic Failover — Route to backups when primary is unhealthy
  • 📡 Event System — Subscribe to connection, health, and failover events
  • 📦 Minimal Footprint — Zero runtime dependencies, <10KB bundle
  • 🔷 TypeScript Ready — Full type definitions with generics

Before & After

// DIY: Managing multiple databases with health checks and failover

const primaryPool = new Pool({ connectionString: PRIMARY_URL });
const replicaPool = new Pool({ connectionString: REPLICA_URL });
const redis = createClient({ url: REDIS_URL });

let primaryHealthy = true;
let replicaHealthy = true;
let redisHealthy = true;

// Manual health check loop
setInterval(async () => {
  try {
    await primaryPool.query('SELECT 1');
    primaryHealthy = true;
  } catch {
    primaryHealthy = false;
    console.log('[HEALTH] Primary unhealthy');
  }
  
  try {
    await replicaPool.query('SELECT 1');
    replicaHealthy = true;
  } catch {
    replicaHealthy = false;
  }
  
  try {
    await redis.ping();
    redisHealthy = true;
  } catch {
    redisHealthy = false;
  }
}, 30000);

// Manual failover logic
function getDatabase() {
  if (primaryHealthy) return primaryPool;
  if (replicaHealthy) {
    console.log('[FAILOVER] Using replica');
    return replicaPool;
  }
  throw new Error('All databases unavailable');
}

// Manual graceful shutdown
process.on('SIGTERM', async () => {
  clearInterval(healthCheckInterval);
  await Promise.all([
    primaryPool.end(),
    replicaPool.end(),
    redis.quit(),
  ]);
  process.exit(0);
});

// Usage
app.get('/users', async (req, res) => {
  const db = getDatabase();
  const { rows } = await db.query('SELECT * FROM users');
  res.json(rows);
});
import { Orchestrator } from 'omni-db';

const db = new Orchestrator({
  connections: { primary: primaryPool, replica: replicaPool, cache: redis },
  failover: { primary: 'replica' },
  healthCheck: {
    interval: '30s',
    checks: {
      primary: async (c) => { await c.query('SELECT 1'); return true; },
      replica: async (c) => { await c.query('SELECT 1'); return true; },
      cache: async (c) => (await c.ping()) === 'PONG',
    },
  },
});

await db.connect();
db.shutdownOnSignal();

// Usage — identical, but with automatic failover
app.get('/users', async (req, res) => {
  const pg = db.get('primary');  // Auto-routes to replica if primary is down
  const { rows } = await pg.query('SELECT * FROM users');
  res.json(rows);
});

What you get: Health monitoring, automatic failover, event system, graceful shutdown, TypeScript types — all in <10KB with zero dependencies.

Installation

npm install omni-db

Quick Start

import { Orchestrator } from 'omni-db';

const db = new Orchestrator({
  connections: {
    primary: prismaClient,
    replica: replicaClient,
    cache: redisClient,
  },
  failover: { primary: 'replica' },
  healthCheck: {
    interval: '30s',
    timeout: '5s',
    checks: {
      primary: async (client) => {
        await client.$queryRaw`SELECT 1`;
        return true;
      },
      cache: async (client) => {
        const pong = await client.ping();
        return pong === 'PONG';
      },
    },
  },
});

// Connect and start health monitoring
await db.connect();

// Get clients (auto-routes to replica if primary is unhealthy)
const client = db.get('primary');

// Check health status
console.log(db.health());
// { primary: { status: 'healthy' }, replica: { status: 'healthy' }, cache: { status: 'healthy' } }

// Disconnect when done
await db.disconnect();

API Reference

new Orchestrator(config)

Creates a new orchestrator instance.

| Option | Type | Description | |--------|------|-------------| | connections | Record<string, any> | Named database client instances | | failover | Record<string, string> | Map primary → backup names | | healthCheck.interval | string | Check interval (e.g., '30s', '1m') | | healthCheck.timeout | string | Timeout per check | | healthCheck.retry.retries | number | Failed attempts before marking unhealthy | | healthCheck.retry.delay | string | Waiting time between retries | | healthCheck.checks | Record<string, Function> | Custom health check functions | | circuitBreaker.threshold | number | Failures before opening circuit (default: 5) | | circuitBreaker.resetTimeout | string | Time before half-open (default: '30s') | | circuitBreaker.use | object | External circuit breaker (opossum, cockatiel) |

Methods

| Method | Returns | Description | |--------|---------|-------------| | connect() | Promise<void> | Connect and start health monitoring | | disconnect() | Promise<void> | Disconnect and stop monitoring | | get(name) | T | Get client (with failover routing) | | execute(name, fn) | Promise<T> | Execute with automatic circuit breaker | | getStats() | Record<string, object> | Get health + circuit breaker stats | | list() | string[] | Get all connection names | | has(name) | boolean | Check if connection exists | | health() | Record<string, ConnectionHealth> | Get health status | | recordSuccess(name) | void | Record success for circuit breaker | | recordFailure(name) | void | Record failure for circuit breaker | | shutdownOnSignal(opts?) | () => void | Register graceful shutdown handlers | | isConnected | boolean | Connection state | | size | number | Number of connections |

Events

db.on('connected', ({ name }) => console.log(`${name} connected`));
db.on('disconnected', ({ name }) => console.log(`${name} disconnected`));
db.on('health:changed', ({ name, previous, current }) => {
  console.log(`${name}: ${previous} → ${current}`);
});
db.on('failover', ({ primary, backup }) => {
  console.log(`Switched from ${primary} to ${backup}`);
});
db.on('recovery', ({ primary, backup }) => {
  console.log(`Recovered ${primary}, was using ${backup}`);
});

TypeScript

Full type inference with generic connections:

import { Orchestrator } from 'omni-db';
import { PrismaClient } from '@prisma/client';
import { Redis } from 'ioredis';

const db = new Orchestrator({
  connections: {
    postgres: new PrismaClient(),
    redis: new Redis(),
  },
});

const prisma = db.get('postgres'); // Type: PrismaClient
const redis = db.get('redis');     // Type: Redis

Documentation

For detailed guides, see the docs/ folder:

| Guide | Description | |-------|-------------| | Getting Started | Installation and basic usage | | Configuration | All configuration options | | Architecture | How components work together | | Health Monitoring | Health checks and status | | Failover | Automatic failover routing | | Circuit Breaker | Prevent cascading failures | | Events | Event system reference | | Observability | Prometheus, logging, metrics | | Middleware | Express, Fastify, Koa, Hono, NestJS | | TypeScript | Type definitions and generics | | Examples | Real-world usage patterns | | Best Practices | Patterns, anti-patterns, and tips | | Error Reference | All errors with causes and solutions |

Philosophy

OmniDB is a thin orchestration layer. It doesn't abstract your databases — it orchestrates them.

You bring:

  • Your database clients (Prisma, Drizzle, pg, Redis, MongoDB...)
  • Your health check logic
  • Your routing decisions

OmniDB provides:

  • Connection registry with O(1) lookup
  • Periodic health monitoring
  • Automatic failover routing
  • Event-driven notifications

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT © Sathvik C