← Blog

The Cron Bug That Only Happens Twice a Year

September 22, 2026

Most scheduling bugs show up constantly, which is exactly what makes them easy to catch — run the job enough times and something breaks soon enough to notice. This one is different: it only exists for a single hour, twice a year, and the rest of the time your schedule behaves exactly as expected. That's what makes it dangerous. It passes every normal test, indefinitely, until the one day it doesn't.

Why "2:30 AM local time" is ambiguous once a year

When clocks fall back for daylight saving time, the hour from 1:00 AM to 2:00 AM happens twice. A schedule defined as "run at 1:30 AM local time" doesn't cleanly map to one instant anymore — there are two 1:30 AMs that day. Depending on how your scheduler resolves that ambiguity, you get one of two outcomes: the job fires twice, 60 minutes apart, or the scheduler treats the second occurrence as already-handled and the job doesn't fire at all.

The same schedule that ran correctly 364 days in a row produces a different, wrong result on exactly one of them — and it's the same day every year, which means the bug is entirely predictable and still catches people off guard, because nobody's watching for a bug that only exists one specific week in autumn.

Double-firing is often the more visible failure, because it tends to produce duplicate side effects — two emails instead of one, two charges instead of one, a report generated twice with slightly different data if anything changed in that 60-minute window. The missed run is quieter and arguably worse: nothing happens, nothing errors, and unless something else is watching for "did this job run today at all," the gap just sits there unnoticed until whatever depended on that run's output goes stale.

The fix is boring, which is why it works

Schedule in UTC, not local time, wherever the choice is actually yours. UTC doesn't observe daylight saving time, so a UTC-anchored schedule doesn't have an ambiguous hour — every timestamp maps to exactly one instant, every day of the year, including the two that break local-time schedules. The tradeoff is that "run at 9 AM for our users" now means picking a UTC offset that's only correct half the year, which is a real constraint for anything genuinely tied to a local business hour — but for anything that doesn't need to track a specific local wall-clock time (most cron jobs, most background processing), UTC removes the entire category of bug.

If local time is unavoidable, the fallback is a monitor that doesn't care what time the job was supposed to run — a heartbeat check-in with a wide enough grace window, or an "has this run at least once today" assertion, rather than a check tied to an exact expected timestamp. That way, whether the DST transition makes the job run twice or zero times, something is watching for the actual outcome instead of trusting the schedule to resolve cleanly on the one day a year it doesn't.

PulseChecker watches your endpoints, cron jobs, and AI agents — and catches the failures that don't announce themselves. Start free.