Your scheduled job got confused by the clock change
Twice a year the local clock skips an hour or repeats one. Jobs scheduled in that hour, or in a different timezone than you think, can quietly run late, early, or not at all. Here's how each scheduler handles it and how to find out the morning it happens, not a week later.
Short answer
Give the job a heartbeat. Create a watch in Did It Run? with the job's schedule in the same timezone the scheduler uses, and add a check-in (a curl to the watch's ping URL) as the job's last step. If a clock change makes the run skip or slip past its grace window, you get a missed alert, and a recovery notice when the next good run arrives. Start free (3 watches, no credit card).
In most of the US, clocks go back one hour on Sunday, November 1, 2026 at 2:00 am local time, and spring forward on Sunday, March 14, 2027 (timeanddate.com, New York). Arizona (outside the Navajo Nation) and Hawaii don't change. Other countries change on other dates: the EU went back on October 25, 2026.
Why clock changes break schedules quietly
A daylight saving change creates two odd hours a year:
- Spring forward: local time jumps from 2:00 to 3:00, so 2:00 to 2:59 doesn't exist that day. A job set for 2:30 has no 2:30 to run at.
- Fall back: local time goes from 1:59 back to 1:00, so 1:00 to 1:59 happens twice. A job set for 1:30 has two candidates.
What happens next depends on the scheduler, and none of these cases produce an error:
- Debian/Ubuntu cron handles changes of less than 3 hours specially: "If the time has moved forwards, those jobs which would have run in the time that was skipped will be run soon after the change. Conversely, if the time has moved backwards by less than 3 hours, those jobs that fall into the repeated time will not be re-run." That only applies to jobs at a fixed time. Jobs with
*in the hour or minute field, or@hourly, are "run based on the new time immediately." Cron uses one timezone for every job, taken from/etc/timezone(Debian cron(8) manual). Other cron implementations may behave differently, so check your own system's manual. - GitHub Actions runs scheduled workflows in UTC by default, and lets you set an IANA timezone. GitHub's docs say that "during DST spring-forward transitions, scheduled workflows in skipped hours advance to the next valid time. For example, a 2:30 AM schedule advances to 3:00 AM" (GitHub Docs: events that trigger workflows).
- n8n's Schedule Trigger uses the workflow's timezone if you set one, otherwise the instance timezone. Self-hosted instances default to America/New York; n8n Cloud tries to detect the owner's timezone at sign-up and falls back to GMT (n8n Schedule Trigger docs).
The quieter problem: a job in UTC, a person in local time
The more common surprise isn't the odd hour itself. It's a scheduler that runs in UTC (GitHub Actions by default, many servers and containers) feeding people who live in local time.
A job at 0 13 * * * UTC lands at 9:00 am in New York in summer and 8:00 am after November 1. Nothing failed, but the report now arrives an hour before the team expects it, and in March it moves back. If something downstream depends on it, such as a file being there by 8:30, that dependency can break with no error anywhere.
Step 1: decide which clock the job follows
Pick one, on purpose:
- Local time if people care about the wall-clock time ("the report by 9am New York time"). Set the timezone explicitly in the scheduler, for example in GitHub Actions:
on:
schedule:
- cron: '0 9 * * 1-5'
timezone: "America/New_York"- UTC if the job feeds other systems that run in UTC and nobody cares about the local hour.
In n8n, set the timezone in the workflow settings rather than relying on the instance default. On a Linux server, check what /etc/timezone says before you assume.
Step 2: keep fixed-time jobs out of the changeover hours
If the job follows local time in a zone that observes daylight saving, avoid scheduling it between 1:00 and 3:00 am local. That's the window that gets skipped or repeated, and the place where schedulers differ the most. Moving a 2:30 job to 3:30 or 4:00 sidesteps both nights.
Step 3: add a heartbeat in the same timezone
Create a watch in Did It Run? with the same schedule and the same timezone as the scheduler, plus a grace window that covers normal run time. Then add the check-in as the last step:
30 4 * * * /opt/jobs/nightly-report.sh && curl -fsS -m 10 --retry 3 https://diditrun.app/p/<your-token> > /dev/nullTo catch runs that start but never finish, call /start at the beginning and the plain ping URL at the end. To report a known failure right away, call /fail. See the cron and GitHub Actions recipes for full examples.
Check-ins are by ping URL today, with /start and /fail variants. Email check-ins are coming soon.
Step 4: check the next run times
The watch page lists the next three due times, each with its timezone label (for example EDT or EST), and the time after which each run counts as missed. Look at it the week of a clock change and make sure it says what you expect.
How the watch behaves on the two odd nights
A watch's schedule is a cron expression evaluated in the timezone you choose, so it follows the local clock:
- A daily 9:00 am New York watch stays at 9:00 am local before and after November 1.
- On the fall-back night, a daily 1:30 am watch expects one run, at the first 1:30 (EDT).
- On the spring-forward day, a daily 2:30 am watch expects the run at 3:30 am EDT (the missing 2:30 moved forward an hour). A run that Debian cron starts "soon after the change", or that GitHub advances to 3:00, arrives before that and counts.
- A run counts as on time if it arrives any time from halfway back to the previous scheduled run until the deadline (scheduled time plus grace). So for a daily job, a run that comes an hour early still counts, and one that comes an hour late is missed unless your grace is longer than an hour.
Alert emails show times with their zone label, so you can tell which 1:30 a message means.
Honest limits
- Early runs aren't flagged. If a UTC job starts arriving an hour early in November, the watch still counts it. If an early run is a problem for you, put the watch in UTC to match the scheduler, and handle the local-time question separately.
- A second run isn't flagged. If a job runs twice in the repeated hour, both check-ins are accepted. Did It Run? tells you when an expected run doesn't arrive; it doesn't detect duplicates.
- It doesn't run or reschedule your job. It only listens for check-ins. The fix for a schedule in the wrong timezone is still in your scheduler.
What you'll see
- Missed: no check-in by the expected time plus grace. A run that was skipped, or that slipped more than the grace window, ends up here.
- Late: an optional early warning while the run is inside its grace window.
- Failed: the job called
/fail. - Recovered: the first good run after a problem.
You get one alert when a watch changes state, not one for every run, plus a recovery notice. Free covers 3 watches with email alerts; Solo ($15/month) adds Slack, Discord and Telegram alerts and a daily digest across all your automations. For other ways a schedule goes quiet, see how to know if an automation didn't run.
FAQ
Does cron run a job twice when the clocks go back?
On Debian and Ubuntu cron, jobs scheduled at a fixed time in the repeated hour are not re-run, according to the cron(8) manual. Jobs with a * in the hour or minute field run by the new clock time, so an hourly job runs in both 1 am hours. Other cron implementations may differ, so check your own system's manual.
What happens to a 2:30 am job when the clocks spring forward?
It depends on the scheduler. Debian cron runs jobs from the skipped hour soon after the change. GitHub Actions, with a timezone set, advances a 2:30 am schedule to 3:00 am. A Did It Run? watch set to 2:30 am in that timezone expects the run by 3:30 am local that day plus grace, so either of those runs counts, and a run that never happens raises a missed alert.
Should the watch use UTC or my local timezone?
Use the same timezone as the scheduler. If the job runs on UTC, a local-time watch would see it shift by an hour twice a year: an hour early still counts, but an hour late is missed unless your grace covers it.
Can Did It Run? tell me if a job ran twice?
No. It alerts when an expected run doesn't arrive, fails, or reports empty output. It doesn't flag duplicate runs.
Can I check in by email instead of a URL?
Not yet. Email check-ins are coming soon. Today every check-in is an HTTP request to the watch's ping URL, with /start and /fail variants.
Is this on the free plan?
Yes. Missed, late, failed and empty detection is included on every plan, including Free (3 watches, email alerts).
Know the next time it doesn't run
Know when your AI agents and automations didn't run. Free for 3 watches.
Start free