Scheduling

Presets

Readable names for common schedules. Each one expands to a six-field expression, and TypeScript rejects any it doesn't recognise.

On this page

Fixed presets

Preset Expression Runs
@every_second * * * * * * Every second
@every_minute 0 * * * * * At the start of every minute
@hourly 0 0 * * * * At the start of every hour
@daily 0 0 0 * * * Every day at midnight
@weekly 0 0 0 * * 0 Sundays at midnight
@monthly 0 0 0 1 * * The 1st of every month at midnight
@yearly, @annually 0 0 0 1 1 * 1 January at midnight

Presets that take a value

Preset Expression Example
@every_<n>_seconds */n * * * * * @every_30_seconds
@every_<n>_minutes 0 */n * * * * @every_15_minutes
@every_<n>_hours 0 0 */n * * * @every_6_hours
@every_<n>_dayOfMonth 0 0 0 */n * * @every_2_dayOfMonth
@every_<n>_months 0 0 0 1 */n * @every_3_months
@every_<n>_dayOfWeek 0 0 0 * * */n @every_2_dayOfWeek
@at_<hour>:<minute> 0 minute hour * * * @at_18:30
@on_<day> 0 0 0 * * day @on_friday
@between_<start>_<end> 0 0 start-end * * * @between_9_17

A few details to keep in mind:

  • Units are always plural, so @every_1_minutes is valid and @every_1_minute isn’t. The fixed presets @every_second and @every_minute are the only singular forms.
  • <n> must be a positive whole number.
  • @at_ takes an hour from 0 to 23 and a minute from 0 to 59. Single digits are fine, and @at_9:5 means 09:05.
  • @on_ takes a full lowercase day name, and the job runs at midnight on that day.
  • @between_ runs at the start of each hour in the range, including the last one. @between_9_17 runs at 09:00, 10:00 and so on through 17:00. The start must be earlier than the end.

@every follows the clock

@every_<n>_<unit> is a step expression, not a stopwatch. It lines up with the clock, not with the moment you started the job, and it has the same limits as any other step.

Preset What actually happens
@every_15_minutes Runs at :00, :15, :30 and :45 past the hour, whenever you started it
@every_7_seconds Runs at 0, 7, … 56 seconds, then 4 seconds later at the next minute
@every_90_seconds Only matches second 0, so it runs once a minute
@every_5_hours Runs at 00:00, 05:00, 10:00, 15:00 and 20:00, then 4 hours later at midnight
@every_3_dayOfMonth Runs on the 1st, 4th, … 28th and 31st, then on the 1st of the next month
@every_5_months Runs on 1 January, 1 June and 1 November
@every_2_dayOfWeek Runs on Sunday, Tuesday, Thursday and Saturday

These are evenly spaced only when <n> divides the field evenly. For seconds and minutes, that means 1, 2, 3, 4, 5, 6, 10, 12, 15, 20 or 30.

Type checking

Any string starting with @ must match a known preset shape, or it won’t compile.

baker.add({ name: "ok", cron: "@at_18:30", callback });

// @ts-expect-error "@noon" isn't a preset
baker.add({ name: "no", cron: "@noon", callback });

The check is on the shape of the string, so an out-of-range value such as @at_25:00 compiles and then throws when the job is created.

Each job takes one preset. To run on two schedules, add two jobs that share a callback, or write the schedule as a six-field expression.

esc

Try overlap, restore or timezone.