Scheduled Work with node-cron

Some work does not belong in a request: rebuilding a search index, expiring sessions, mailing a nightly digest. node-cron 3,280 (ISC, 4.6.0, github.com/node-cron/node-cron (https://github.com/node-cron/node-cron 3,280 ), npm 2,036 i node-cron) runs it on a cron expression inside your process, with no external scheduler. Version 4 accepts six fields, so the leading one is seconds; five fields still mean the classic minute-first form.

A recurring task with overlap protectionJavaScript
import cron from 'node-cron';
let runs = 0;
const task = cron.schedule('*/2 * * * * *', async (ctx) => {
  console.log(`run ${++runs} triggered ${ctx.triggeredAt.toISOString().slice(11, 19)}`);
  if (runs !== 3) return;
  console.log('next run:', task.getNextRun()?.toISOString().slice(11, 19));
  await task.stop();
  console.log('task status:', task.getStatus());
}, { name: 'reindex', timezone: 'UTC', noOverlap: true });
console.log('valid:', cron.validate('0 3 * * *'), '| tasks:', cron.getTasks().size);
Output
valid: true | tasks: 1
next run: 12:20:04
run 1 triggered 12:20:04
run 2 triggered 12:20:06
run 3 triggered 12:20:08
next run: 12:20:10
task status: stopped

Four options carry most of the weight. timezone pins the schedule to wall-clock time in a named zone, so "03:00" survives daylight saving instead of drifting an hour twice a year. noOverlap skips a tick while the previous run is still going, the difference between a slow job and a pile of slow jobs. maxExecutions stops a task after a fixed count, and maxRandomDelay spreads a fleet of identical instances over a window so they do not all hit the database at 03:00:00. Tasks also expose start(), destroy(), execute() and lastRun().

The catch is that in-process scheduling multiplies with your processes: four cluster workers means four nightly digests. Either run the scheduler as its own single instance, or take a lock — SET schedule:digest <id> NX EX 3600 in Redis 2,763 — as the first thing the job does. Keep jobs short and idempotent; anything that takes minutes belongs in the queue of BullMQ Queues.