View all files | ||||
Job scheduling for Node.js with overlap prevention, distributed coordination, and background tasks. Schedule recurring tasks with cron expressions, prevent overlapping runs, coordinate across multiple instances, and run heavy jobs in isolated background processes. Zero dependencies, written in TypeScript.
Long-running tasks can overlap when the next tick fires before the previous run finishes. noOverlap skips a run instead of stacking them:
Running multiple instances of your app? distributed: true ensures only one instance executes each scheduled fire. Out of the box it uses an env-var flag; for high availability, plug in a Redis coordinator:
Pass a file path instead of a function to run a job in an isolated forked process, so heavy work never blocks your event loop:
Bundlers: background tasks fork a helper that node-cron resolves relative to its own files in node_modules. If you bundle your app (esbuild, webpack, Rollup, etc.), mark node-cron as external so it stays on disk (--external:node-cron, or externals: ['node-cron'] in webpack). Otherwise the fork fails with Cannot find module '.../daemon.js'. Inline function tasks are unaffected.
Every task exposes a single consistent interface for control and inspection:
Tasks emit lifecycle events for observability:
All events: task:started, task:stopped, task:destroyed, task:failed, execution:started, execution:finished, execution:failed, execution:missed, execution:overlap, execution:maxReached, execution:skipped. See Events & Observability.
| second | 0-59 (optional) |
| minute | 0-59 |
| hour | 0-23 |
| day of month | 1-31 (or L for the last day; L-3 offset from last; 15W, LW for nearest weekday) |
| month | 1-12 (or names) |
| day of week | 0-7 (or names, 0 or 7 are Sunday; 2#3, 5L) |
Supports ranges (1-5), steps (*/2), lists (1,15), named months/weekdays, L (last day of month), L-n (offset from the last day), # (nth weekday), <weekday>L (last weekday of month), W (nearest weekday), and ? (alias for * in the day fields, for Quartz-style expressions). See the Cron Syntax guide.
An inverted range wraps around the field instead of being rejected: 22-2 in the hour field means 22:00 through 02:59 (22,23,0,1,2), and sat-sun in the day-of-week field means saturday,sunday.
The W modifier in the day-of-month field fires on the nearest weekday (Monday-Friday) to a given day, without crossing the month boundary: 15W is the nearest weekday to the 15th, 1W the first weekday of the month, and LW the last weekday of the month. Only weekends are adjusted for; there is no holiday awareness.
The L-n form fires n days before the last day of the month (L-3 is the third-to-last day). In months where the offset reaches before the 1st (e.g. L-29 in February), it simply does not fire that month.
Note on Quartz: L, L-n, W, LW, #, <weekday>L and ? are borrowed from Quartz, but node-cron is not Quartz-compatible. Two differences matter:
? is accepted purely as an alias for * in the day fields so Quartz-style expressions parse, not as a semantic compatibility guarantee.
See Scheduling Options for the full list.
Schedules match wall-clock time in the task's timezone. Across a daylight-saving fall-back the repeated hour runs once, so a sub-hourly schedule (for example */15) can pause for up to the length of the DST shift during that hour. If you need a fixed interval to keep firing uninterrupted across DST transitions, use a zone without DST, for example timezone: 'UTC'. See Timezones & DST for the full model.
v4 is a TypeScript rewrite with a smarter scheduler and a streamlined API. See the Migration Guide.
node-cron is zero-dependency infrastructure used in production by 220,000+ repositories. If it is part of your stack, sponsoring helps keep it tested, DST-correct, and maintained.
Become a sponsor on GitHub Sponsors or Open Collective.
Feel free to submit issues and enhancement requests here.
In general, we follow the "fork-and-pull" Git workflow.
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
Please do not contribute code you did not write yourself, unless you are certain you have the legal ability to do so. Also ensure all contributed code can be distributed under the ISC License.
node-cron is under ISC License.