node-cron

A lightweight Node.js library for scheduling jobs on cron expressions, dates, or Luxon DateTimes, with built-in time zone support.

Library
npm
v4.4.0
8,950 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
87 /100 Excellent
Development Activity 96
Maintenance 80
Community 72
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
80 /100 Excellent
Architecture 82
Code Quality 92
Innovation 74
Learning Curve 70

Cron (published to npm as cron) is a scheduling library for Node.js that runs functions or shell commands on a six-field cron expression, adding a seconds slot on top of the standard five-field Unix format. Jobs can also be scheduled against a plain JS Date or a Luxon DateTime for one-off execution instead of a recurring pattern, and every job can be pinned to a named IANA time zone or a fixed UTC offset via its Luxon-backed CronTime engine.

Beyond basic scheduling, the library handles the operational edge cases that come up in production: a waitForCompletion flag prevents overlapping runs when a tick callback is still executing, a configurable threshold decides whether a missed deadline (caused by a slow or busy process) should still fire or be skipped with a warning, and an errorHandler callback centralizes error handling instead of letting failures in onTick go unnoticed. Standalone helpers (sendAt, timeout, validateCronExpression) expose the same parsing engine without requiring a full CronJob instance.

What You Get

  • Six-field cron syntax (with a seconds slot) parsed and validated by a dedicated CronTime class
  • A CronJob class with both a classic positional constructor and a CronJob.from({...}) object-style factory
  • Time zone and UTC offset aware scheduling, backed by Luxon, with a runtime guard against setting both at once
  • Overlap and missed-deadline controls (waitForCompletion, threshold) for production-grade job scheduling
  • TypeScript types generated under strict compiler settings, plus standalone sendAt/timeout/validateCronExpression helpers

Common Use Cases

  • Scheduled data backups - ops teams run nightly backup or maintenance scripts on a cron expression tied to a specific time zone
  • Recurring notification digests - product teams fire periodic digest or reminder jobs (e.g. every Monday at 9am) using named day/month patterns
  • Delayed one-off tasks - developers schedule a single future task with a JS Date or Luxon DateTime instead of writing a recurring pattern
  • Guarding long-running jobs - teams with slow async tick callbacks use waitForCompletion to stop overlapping executions from piling up

Under The Hood

Architecture

The package is organized around a clean split between time computation and job lifecycle: src/time.ts (CronTime) owns cron-expression parsing, field validation against constants.ts’s ranges/aliases, and next-fire-time computation via Luxon, while src/job.ts (CronJob) owns scheduling state, start/stop/fireOnTick lifecycle, callback registration, and self-rescheduling setTimeout chaining (including splitting waits longer than Node’s ~24.8-day setTimeout ceiling into repeated MAXDELAY chunks). Shared runtime validation, such as rejecting a CronJob/CronTime constructed with both timeZone and utcOffset, lives in src/errors.ts and is called from both classes to keep the invariant enforced in one place. src/index.ts re-exports the public surface (CronJob, CronTime, sendAt, timeout, validateCronExpression) and type contracts from src/types/, keeping the module boundary narrow and stable.

Tech Stack

Written in TypeScript compiled to CommonJS/ES2015 via tsc -b, with a single runtime dependency on luxon (plus its @types/luxon) for time zone and DateTime handling — no other runtime dependencies. The devDependency set is oriented around automation: Jest with the @swc/jest transform and @fast-check/jest for property-based fuzz testing, ESLint (typescript-eslint) and Prettier enforced through Husky + lint-staged pre-commit hooks, and semantic-release wired to GitHub Actions for automated versioning, changelog generation, and npm publishing.

Code Quality

Tests are split by concern (cron.test.ts, crontime.test.ts, errors.test.ts, threshold.test.ts) plus a dedicated cron.fuzz.ts using property-based fuzz testing against @fast-check/jest — a step beyond typical example-based unit tests for a scheduling library where edge cases in time math matter. tsconfig.json enables strict plus several stricter flags rarely turned on together (noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitOverride, noUnusedLocals), and CI runs a dedicated CodeQL workflow and an OpenSSF Scorecard workflow alongside the test suite, reflecting active attention to supply-chain and static-analysis signal, not just green tests.

API Design The primary CronJob constructor takes up to thirteen positional parameters, a holdover from the library’s long history, but the CronJob.from({...}) static factory offers a fully named, object-based alternative that most new usage in the README favors. Standalone sendAt/timeout/validateCronExpression functions let callers use the parsing engine without instantiating a class at all, and errors are surfaced through a dedicated CronError hierarchy rather than generic Error throws, giving consumers a stable type to catch against.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers