Developer guide

node-cron in Node.js: Schedule Jobs With Cron Syntax

Node.js has no built-in cron. The simplest answer is node-cron — a tiny library that runs functions on the exact cron expressions you already know. This guide covers install, every-minute and hourly schedules, timezones, the alternatives (node-schedule, the cron package), and the production traps that silently kill jobs.

Benjamin Rotshtein

Written by Benjamin Rotshtein

Updated

How do I schedule a job in Node.js with cron syntax?

Install node-cron and call Cron.schedule(expr, fn) with a standard cron expression — for example * * * * * for every minute or 0 0 * * * for midnight. Pass an options object with a timezone to control when it fires. Keep the process alive and handle errors, because a crashed process silently stops the schedule.

Install
npm install node-cron
Every minute
cron.schedule('* * * * *', fn)
Timezone
cron.schedule('0 9 * * *', fn, { timezone: 'Asia/Kolkata' })

Install and first job

npm install node-cron

const cron = require("node-cron");

// every minute
cron.schedule("* * * * *", () => {
  console.log("tick at", new Date().toISOString());
});

That is the whole API surface you need for 95% of cases. The expression is standard cron: minute hour day-of-month month day-of-week, with the 6-field seconds form also supported.

Common schedules

cron.schedule("0 * * * *", () => syncData());        // every hour
cron.schedule("*/30 * * * *", () => ping());         // every 30 minutes
cron.schedule("0 0 * * *", () => dailyReport());     // every day at midnight
cron.schedule("0 0 * * 0", () => weeklyCleanup());   // every Sunday midnight
cron.schedule("0 9 * * 1-5", () => openMarket());    // weekdays at 9 AM
cron.schedule("*/10 * * * * *", () => probe());      // every 10 seconds

Note the seconds example: node-cron accepts the 6-field format in the first position, so sub-minute intervals are native here even though Linux cron cannot do them.

Running in a specific timezone

By default node-cron uses the server’s local time — which is UTC on most cloud hosts, whatever your laptop says. Pass a timezone to pin the schedule to a real timezone:

cron.schedule("0 9 * * *", () => sendDigest(), {
  timezone: "Asia/Kolkata",   // 09:00 IST regardless of server TZ
});

cron.schedule("0 0 * * *", () => nightlyTask(), {
  timezone: "Etc/UTC",        // pin to UTC explicitly
});

Use an IANA identifier ( America/New_York, Europe/Berlin, Asia/Kolkata) — not abbreviations like IST, which are ambiguous and break around DST. The cron timezone guide covers this in depth.

node-cron vs node-schedule vs the cron package

All three schedule jobs in Node; they differ in scope. node-cron is the lightest — cron syntax, timezone option, zero dependencies, perfect for typical periodic jobs. node-schedule shines for one-off runs (scheduleJob(new Date(...))) and recurrence rules that are awkward in cron. The cron package is the heavyweight with more features (including timezone-aware parsing and multiple events). For most services, node-cron is the right default; switch only when you hit its limits.

Production safety: keep the process alive and catch errors

Two rules prevent the classic “node-cron not working in production” reports. First, node-cron is in-process: if the Node process exits, the schedule is gone. Uncaught exceptions are the usual killer, so every callback should fail loudly without crashing:

cron.schedule("0 * * * *", async () => {
  try {
    await syncData();
  } catch (err) {
    console.error("hourly sync failed", err);
    // alert: notify, push to queue, etc.
  }
});

Second, keep the process supervised. Run under PM2 or systemd with auto-restart so a crash or a deploy brings the scheduler back. If you need the job to survive even a dead process, prefer an external scheduler — a real crontab, a Kubernetes CronJob or a cloud function timer.

Frequently asked questions

What is node-cron and how do I install it?

node-cron is a small npm library that runs JavaScript functions on cron schedules using the familiar 5-field (or 6-field with seconds) syntax. Install it with npm install node-cron, then call cron.schedule(expression, callback). It works in plain Node.js, Express, and any long-running process that stays alive.

How do I run a function every minute in node-cron?

cron.schedule('* * * * *', () => { ... }) runs the callback once per minute. For every 30 minutes use '* /30 * * * *' (no space: '*/30 * * * *'); for every hour use '0 * * * *'. node-cron also accepts a seconds field, so '*/10 * * * * *' runs every 10 seconds.

How do I set the timezone in node-cron?

Pass a timezone option as the third argument: cron.schedule('0 9 * * *', fn, { timezone: 'Asia/Kolkata' }) runs at 09:00 IST. The default is the server's local time. Use an IANA timezone name (not an abbreviation like IST or UTC+5) so DST transitions are handled correctly.

node-cron vs node-schedule vs the cron package: which should I use?

node-cron is the lightest and most popular for standard cron syntax and a timezone option. node-schedule is better for one-off times and more complex recurrence rules. The 'cron' package is a heavier full scheduler with many options. For most apps, node-cron covers everything: stable 5/6-field expressions, timezone support and zero dependencies.

Why does my node-cron job stop after a while or never run in production?

node-cron schedules timers inside your Node.js process — if the process exits (uncaught exception, deployment restart, or the server shutting down idle), the schedule dies with it. Production fixes: wrap callbacks in try/catch so errors cannot crash the process, log failures, keep the process alive (no early process.exit), and use a process manager like PM2 or systemd to restart it on failure.

How do I catch errors in node-cron jobs?

node-cron does not catch callback exceptions for you; an uncaught error inside the callback can crash the process. Wrap the body in try/catch (or .catch for promises) and log the error, optionally with retry or alerting. This is the single most common production failure for node-cron jobs.

Related guides

Build a schedule that survives

Generate the cron expression in plain English and preview the next fire times before pasting it into node-cron — the same syntax works everywhere.