Schedules

Intervals and cron expressions, timezones and daylight saving, missed windows, and how punctual a job is.

A job's schedule is either an interval or a cron expression, always in a named timezone. Set it when you create the job, change it on the job's page under What it runs and when, or pass it to sdk.crons.

Intervals

Every N seconds, minimum 60. A shorter interval is refused, not rounded: for anything faster, a queue is the right tool, not a schedule.

An interval is measured from the previous scheduled instant, not from when the last run finished, so a job that takes eight seconds never drifts to every sixty-eight.

Cron expressions

A standard five-field expression, minute hour day-of-month month day-of-week, plus the usual macros: @hourly, @daily, @weekly, @monthly, @yearly. Ranges, lists, steps and three-letter names all work, and Sunday is accepted as both 0 and 7.

ExpressionFires
*/15 * * * *Every 15 minutes
0 7 * * mon-fri7:00 on weekdays
30 2 1 * *2:30 on the 1st of every month
@dailyMidnight, every day

Two things about cron expressions surprise almost everyone:

  • Setting both day fields means OR, not AND. 0 0 1 * mon is "the 1st and every Monday", not "Mondays that fall on the 1st".
  • Expressions run in the job's own timezone. 0 2 * * * means 2am where you set it, and it stays 2am across daylight saving: its UTC offset shifts, its local time does not. The timezone is an IANA name (America/New_York, Europe/Berlin, UTC); an unknown one is refused.

Daylight saving

Daylight saving is handled explicitly rather than left to chance:

  • On the day an hour is skipped, a job scheduled inside the gap runs at the first moment it can (02:30 becomes 03:30 local) instead of being silently skipped for the day.
  • On the day an hour repeats, the job runs once, on the first occurrence. Running twice would be a duplicate invoice; running early is merely early.

Check it before you save

Use the Next runs panel in the editor, or sdk.crons.preview, before you save. Real timestamps prove what a schedule does; a description of one only restates what you typed, and it cannot show you that your daylight-saving assumption was wrong.

const nextRuns = await sdk.crons.preview({
  scheduleKind: "cron",
  cronExpression: "0 0 1 * mon", // the 1st AND every Monday
  timezone: "America/New_York",
});
// The real fire times, as ISO strings, in order. Pass `count` for more or fewer.

Missed windows are skipped, never replayed

If the platform is down from 01:00 to 07:00, an hourly job does not wake up owing six runs. It runs once, and that run records that six windows were missed (missedWindows on the run).

Replaying is almost never what a scheduled job wants (six duplicate invoice emails), and a catch-up switch would put that one checkbox away. So skipping is the only behavior, and the count is kept, because a skip nobody can see is indistinguishable from a gap where nothing was due.

How punctual a job is

The scheduler checks for due jobs every 15 seconds. A job fires at or after its due time, never before, and how late it can be is bounded by that check: a job due at 02:00:00 starts somewhere in 02:00:00 to 02:00:15, a little later when many jobs are due at once.

A job whose work spans many turns takes them one at a time, in turn with every other app's waiting work, so a long job finishes later than its start time suggests, but never blocks anyone else's.

If you need sub-minute precision, you want a queue, not a schedule.

What happens to the schedule when a run fails

Nothing: a failed job is still rescheduled. A job that failed at 02:00 is still due at 03:00. Leaving it due would make every check retry it immediately, turning one broken job into a loop hammering whatever it talks to. Retries of a failed turn have their own short timetable, described in Runs, failures and Resume.

The failure count is shown on the job, but it never switches a job off on its own. Silently disarming your infrastructure because a downstream API had a bad hour is exactly the failure this feature exists to avoid. Pause a job yourself to hold it; its schedule and history are kept.

Next

On this page