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

@plus99/cronx

v1.0.2

Published

Reliable Cron for Node.js

Readme

@plus99/cronx

A reliable, distributed-ready cron job scheduler for Node.js designed as a drop-in replacement for node-cron.

Features

  • 🕒 Seconds precision cron support - Supports standard and extended cron expressions with seconds
  • 💾 Multiple storage backends - Memory, SQLite, PostgreSQL, Redis
  • 🔄 Automatic retries - Configurable retry mechanisms with fixed/exponential backoff
  • 🔒 Distributed locking - Prevents duplicate execution across multiple workers
  • 📊 Built-in metrics - Prometheus metrics for monitoring and observability
  • Timeout handling - Job cancellation with configurable timeouts
  • 🎯 TypeScript support - Full type definitions included

Installation

npm install @plus99/cronx

Quick Start

import { Cronx } from '@plus99/cronx';

// Create scheduler with in-memory storage
const cronx = new Cronx({
  storage: 'memory://',
  workerId: 'my-worker'
});

// Schedule a job
await cronx.schedule('*/5 * * * * *', async () => {
  console.log('Job executed every 5 seconds!');
  return { status: 'success' };
}, {
  name: 'my-job',
  retries: 3,
  timeout: 10000
});

// Start the scheduler
await cronx.start();

Storage Backends

Memory (Development)

const cronx = new Cronx({ storage: 'memory://' });

SQLite (Single Instance)

const cronx = new Cronx({ storage: 'sqlite://./jobs.db' });

PostgreSQL (Production)

const cronx = new Cronx({ 
  storage: 'postgresql://user:password@localhost:5432/cronx' 
});

Redis (High Performance)

const cronx = new Cronx({ storage: 'redis://localhost:6379' });

Job Configuration

await cronx.schedule('0 9 * * 1', jobFunction, {
  name: 'weekly-report',
  retries: 5,
  backoff: 'exponential',
  timeout: 30000,
  onSuccess: (result) => console.log('Success:', result),
  onError: (error) => console.error('Failed:', error)
});

Options

  • name - Unique job identifier
  • retries - Number of retry attempts (default: 0)
  • backoff - Retry strategy: 'fixed' or 'exponential' (default: 'fixed')
  • timeout - Job timeout in milliseconds (default: 30000)
  • onSuccess - Success callback function
  • onError - Error callback function

Job Management

// Pause a job
await cronx.pauseJob('my-job');

// Resume a job
await cronx.resumeJob('my-job');

// Run a job immediately
await cronx.runJob('my-job');

// Remove a job
await cronx.unschedule('my-job');

// Get job details
const job = await cronx.getJob('my-job');

// List all jobs
const jobs = await cronx.listJobs();

Monitoring & Statistics

// Get overall statistics
const stats = await cronx.getStats();
console.log(stats);
// { totalJobs: 5, activeJobs: 3, pausedJobs: 2, isRunning: true }

// Get job-specific statistics
const jobStats = await cronx.getJobStats('my-job');
console.log(jobStats);
// { totalRuns: 100, successfulRuns: 95, failedRuns: 5, averageDuration: 1250 }

// Get job execution history
const runs = await cronx.getJobRuns('my-job', 10);
console.log(runs);

Prometheus Metrics

Enable metrics collection for monitoring:

const cronx = new Cronx({
  storage: 'redis://localhost:6379',
  metrics: true
});

// Get metrics in Prometheus format
const metrics = await cronx.getMetrics();

Available metrics:

  • cronx_jobs_total - Total number of scheduled jobs
  • cronx_job_executions_total - Total job executions by status
  • cronx_job_duration_seconds - Job execution duration histogram
  • cronx_active_jobs - Currently active jobs gauge

Cron Expressions

Cronx supports both standard 5-field and extended 6-field cron expressions:

// Standard format (minute hour day month weekday)
'0 9 * * 1'        // Every Monday at 9:00 AM
'*/15 * * * *'     // Every 15 minutes

// Extended format with seconds (second minute hour day month weekday)
'*/30 * * * * *'   // Every 30 seconds
'0 0 12 * * 1-5'   // Weekdays at noon

Error Handling

try {
  await cronx.schedule('invalid-cron', async () => {});
} catch (error) {
  console.error('Invalid cron expression:', error.message);
}

// Job-level error handling
await cronx.schedule('*/5 * * * *', async () => {
  // Job might fail
  if (Math.random() > 0.8) {
    throw new Error('Random failure');
  }
  return { success: true };
}, {
  name: 'failing-job',
  retries: 3,
  onError: (error, attempt) => {
    console.log(`Attempt ${attempt} failed:`, error.message);
  }
});

Distributed Execution

When running multiple Cronx instances with shared storage, distributed locking ensures only one instance executes each job:

// Worker 1
const worker1 = new Cronx({
  storage: 'postgresql://localhost/cronx',
  workerId: 'worker-1'
});

// Worker 2
const worker2 = new Cronx({
  storage: 'postgresql://localhost/cronx',
  workerId: 'worker-2'
});

// Both schedule the same job - only one will execute at a time
await worker1.schedule('*/1 * * * *', jobFunction, { name: 'shared-job' });
await worker2.schedule('*/1 * * * *', jobFunction, { name: 'shared-job' });

API Reference

Constructor

new Cronx(options: CronxOptions)

Methods

  • start() - Start the scheduler
  • stop() - Stop the scheduler
  • schedule(schedule, handler, options) - Schedule a new job
  • unschedule(name) - Remove a job
  • pauseJob(name) - Pause a job
  • resumeJob(name) - Resume a job
  • runJob(name) - Execute a job immediately
  • getJob(name) - Get job details
  • listJobs() - List all jobs
  • getStats() - Get system statistics
  • getJobStats(name?) - Get job statistics
  • getJobRuns(name, limit?) - Get job execution history
  • getMetrics() - Get Prometheus metrics

License

MIT License - see LICENSE file for details.