Skip to content
Get started
Get started
Cron Recipes: Intervals, Timezones, Chained Repeats
guide · cron jobs

The schedules you actually need.

Three shapes cover almost every recurring job: a fixed interval, a wall-clock time in a real timezone, and a job that re-arms itself only once the previous run finished.

Use every instead of a cron pattern when you want fixed-rate scheduled slots. The next slot is anchored to the previous scheduled time, not to completion of the generated job. With the default preventOverlap: true, a still-active previous generation blocks another one from being enqueued:

await queue.upsertJobScheduler('heartbeat', {
every: 60000, // every minute
limit: 100, // optional: stop after 100 runs
}, {
data: { check: 'health' },
});

CLI equivalent: bunqueue cron add heartbeat -q system -d '{"check":"health"}' -e 60000.

Pass an IANA timezone (like Europe/Rome or America/New_York) and the pattern is evaluated in that timezone, daylight saving included:

// 6 PM New York time, weekdays only
await queue.upsertJobScheduler('end-of-day', {
pattern: '0 18 * * 1-5',
timezone: 'America/New_York',
}, {
name: 'end-of-day',
data: { type: 'summary' },
});

From the CLI, pass --timezone (-z):

Terminal window
bunqueue cron add daily-report -q reports -d '{"type":"daily"}' \
-s "0 9 * * *" -z Europe/Rome

For simple repetition tied to job completion, adding a job with the repeat option also works: the job re-enqueues itself every milliseconds after each successful completion. Here limit is the number of successors, so total executions are the initial job plus at most limit repeats. Failed terminal jobs do not create a successor.

await queue.add('sync', { source: 'crm' }, { repeat: { every: 30000, limit: 10 } });

repeat.pattern on queue.add uses the same cron parser as named schedulers. The directly added generation runs first; every successful completion creates the next generation at the calculated cron deadline. tz, startDate, endDate, offset, limit, and immediately stay attached to the chain, and the chain survives a SQLite-backed broker restart.

An offset shifts each cron tick without skipping a tick whose shifted deadline is still in the future. Negative offsets advance to the next future shifted tick instead of creating a zero-delay loop. For interval repeats, the offset sets the first successor phase and later generations continue on every cadence; immediately applies only to the directly added generation.

Job Schedulers from the QueueNamed repeatable schedules on the Queue object
Cron Jobs in BunYour first schedule, in every SDK and from the CLI
Cron ReferenceExpression syntax, every scheduler option, MCP