Cuckoo

Cron Schedule, Time Zone and Grace Period

Updated

A heartbeat check is only as good as its schedule. Set it too tight and you get alerts every time a job runs a few minutes slow. Set it too loose and a broken job goes unnoticed for hours. Time zones and daylight saving time add a twist: the server, cron, and the monitor all need to agree on what "02:30" means.

This guide explains the two schedule types Cuckoo offers, how cron behaves around DST switches, and how to choose a grace time that is quiet when things are fine and fast when they are not.

How Cuckoo decides a ping is late

Every check has an expected schedule and a grace time. After each ping, Cuckoo computes when the next one is due. If the deadline (due time plus grace) passes without a ping to https://cuckoo.metastic.ch/ping/YOUR-UUID, the check goes down and alerts are sent. A late ping that arrives afterwards brings it back up with a recovery message.

Optionally, a max runtime adds a second clock: if a /start ping is not followed by success or failure within that time, the check goes down even though the schedule has not passed yet.

Period or cron expression?

Simple period

A period says "expect a ping every N minutes, hours or days". The next deadline is the last ping plus the period plus grace. Use it when:

  • the job runs at a fixed interval, for example every 5 or 15 minutes;
  • the job is started by something other than a clock, such as a worker loop that sleeps between runs;
  • exact wall-clock times do not matter.

Cron expression with time zone

A cron expression says "expect a ping at these wall-clock times" and is evaluated in the IANA time zone you choose. Use it when:

  • the job runs at specific times, like 30 2 * * *;
  • the job does not run every day, for example weekdays only (0 7 * * 1-5). A 24-hour period would alert on Saturday morning; the cron expression knows the weekend is quiet;
  • you want the check and the crontab to be obviously identical.

Copy the expression straight from the crontab or timer so both stay in sync.

Use IANA time zone names

Choose zone names like Europe/Zurich, America/New_York or UTC, not abbreviations like CET or EST. IANA names include the DST rules for the region; abbreviations are ambiguous and often do not switch.

Find out which zone the server's cron uses:

timedatectl | grep "Time zone"
# Time zone: Europe/Zurich (CET, +0100)

cat /etc/timezone 2>/dev/null || readlink /etc/localtime

Classic cron uses the system time zone. cronie also supports a CRON_TZ variable in the crontab to evaluate entries in another zone; check man 5 crontab on your system before relying on it:

CRON_TZ=UTC
0 3 * * * /usr/local/bin/report.sh && curl -fsS -m 10 --retry 5 -o /dev/null https://cuckoo.metastic.ch/ping/YOUR-UUID

Whatever cron uses, set the same zone on the Cuckoo check.

How cron handles daylight saving time

Vixie cron and its descendants (cronie, Debian's cron) treat clock changes of less than three hours specially, and only for jobs that run at a specific time or less often than hourly:

  • Spring forward: jobs scheduled in the skipped hour (for example 02:30 in Central Europe) run immediately after the change instead of being skipped.
  • Fall back: jobs scheduled in the repeated hour run only once, not twice.
  • Frequent jobs (every minute, */15, hourly wildcards) are scheduled normally by the new local time.

Other schedulers behave differently. systemd timers evaluate OnCalendar= in local time unless you add a zone, and Kubernetes CronJobs use the timeZone field or the controller's zone. When in doubt, the safest options are:

  1. Schedule fixed-time jobs outside 01:00–03:00 local time in zones with DST.
  2. Or run the server, the crontab and the check in UTC, which has no DST.

Choosing a grace time

The grace time absorbs normal variation. A good starting point is:

grace = longest normal run time + scheduling jitter + a safety margin

  • Run time: how long the job takes before it sends the success ping. Look at the durations Cuckoo records when you use /start pings.
  • Jitter: cron starts on the minute; systemd timers with RandomizedDelaySec= or cloud schedulers may start minutes late.
  • Margin: allow for a slow night without paging anyone.

If a job's duration varies a lot, do not inflate the grace time. Send /start and set a max runtime. The grace time then only needs to cover start-up jitter, and hung runs are caught by the max runtime.

Examples

Job Schedule on the check Time zone Grace Max runtime
Queue worker heartbeat every minute Period 1 min (n/a) 3 min none
Cache warm-up every 15 min */15 * * * * UTC 5 min 10 min
Hourly import, 2–8 min long 5 * * * * Europe/Zurich 15 min 30 min
Nightly database dump 30 1 * * * Europe/Zurich 30 min 2 h
Weekday report at 07:00 0 7 * * 1-5 America/New_York 20 min none
Weekly full backup, 1–4 h 0 3 * * 0 UTC 1 h 6 h
Monthly invoice run 0 6 1 * * Europe/Zurich 2 h 4 h

Troubleshooting

  • Alert every day exactly one hour after the job ran. The check is in a different zone than cron, or one side does not follow DST. Compare timedatectl with the check's zone.
  • Alert only on the DST weekend. The job is scheduled in the skipped or repeated hour. Move it, or use UTC.
  • Alerts on weekends for a weekday job. The check uses a period instead of the cron expression.
  • Frequent false alerts. The grace time is smaller than the normal variation. Look at recorded durations and increase it, or add a max runtime and keep the grace short.

FAQ

Should I run everything in UTC?

UTC avoids DST surprises entirely and is a solid default for servers. Business jobs that must happen at a local time, such as a report before the office opens, are easier to reason about in the local IANA zone.

Can the grace time be shorter than the job's run time?

Only if you send a /start ping and rely on the max runtime for long runs. With success-only pings, the grace time must cover the whole run, otherwise every slow run triggers an alert.

What happens if a job runs earlier than expected?

Cuckoo alerts on pings that are missing or late, and on reported failures. A run that finishes early still sends its ping, so it keeps the check up. If runs are regularly early, adjust the schedule so the history stays readable.

Related guides

All guides · Compare Cuckoo with other tools

Send feedback

Ideas, bugs, questions: we read every message. Or write to hello@metastic.ch.