n8n Schedule Trigger and Daylight Saving Time, Tested

automation
A weathered bronze sundial on a mossy stone pedestal in a grassy field at golden hour, its gnomon casting a sharp shadow across the dial, a metaphor for n8n Schedule Trigger timing around daylight saving time
A schedule is only as right as the timezone it's evaluated in. Daylight saving time is when the wrong one shows.

The n8n Schedule Trigger runs in the workflow's own timezone setting first, then the instance's GENERIC_TIMEZONE, and when neither is set it falls back to America/New_York, not UTC and not your server's clock. If your schedule fires at the wrong time, set the timezone explicitly; if it's set correctly, daylight saving time is handled for normal business-hour schedules, but jobs placed between 1:00 and 3:00 AM can move or run an extra time. We tested both on October 19, 2026, two weeks before US clocks fall back on November 1.

Here's why we bothered. Every November and March, some client asks why the morning report showed up at 8 instead of 9, or why an hourly sync posted two batches within 15 minutes. The internet's answer is usually "set GENERIC_TIMEZONE," which is right but incomplete. We wanted to know exactly what n8n does around the clock change, so we tested the real code instead of guessing.

How did we test the n8n Schedule Trigger?

Three parts, all against n8n 2.44.3 (the version we run in production):

  • Reading the source. In 2.44.3, the Schedule Trigger converts each rule into a cron expression and hands it to n8n's ScheduledTaskManager, which creates a job with the cron npm package (v4.4.0) and passes the workflow's timezone straight into it. So the cron library's DST behavior is n8n's DST behavior.
  • A simulated clock. We loaded that exact cron@4.4.0 from inside the official n8nio/n8n:2.44.3 Docker image, created jobs the same way n8n does, and ran a fake clock through November 1, 2026 and March 14, 2027 in America/Chicago, logging every fire.
  • A live instance. We booted n8n 2.44.3 in Docker with different timezone variables, imported two workflows with a Schedule Trigger, published them and read the executions back from the database.

We also pulled our own n8n instance through the public API to see how many scheduled workflows were exposed. More on that below.

Which timezone does n8n actually use?

n8n picks the timezone in this order:

  1. Workflow settings → Timezone, if you set one.
  2. GENERIC_TIMEZONE on the instance.
  3. America/New_York, the hardcoded default. The n8n timezone docs list it, and we confirmed it in the 2.44.3 source.

The live test matched that order exactly:

  • Container TZ=America/Chicago, no GENERIC_TIMEZONE: the workflow with no timezone setting reported America/New_York (UTC-04:00). The TZ variable did nothing for the schedule.
  • GENERIC_TIMEZONE=America/Chicago: the same workflow reported America/Chicago (UTC-05:00).
  • Workflow setting America/Los_Angeles: reported America/Los_Angeles (UTC-07:00) in both runs, overriding the instance.

The TZ variable is the trap. Lots of Docker guides tell you to set both TZ and GENERIC_TIMEZONE. TZ is harmless and keeps container logs readable, but if it's the only one you set, your Central Time schedules run on Eastern Time, one hour early. A team in Dallas notices that. A team in Mexico City or Madrid gets a bigger, stranger offset and usually blames the cron expression.

A handy check: every Schedule Trigger execution includes a Timezone field in its output, like America/Chicago (UTC-05:00). Open the latest execution and read it. That's faster than any amount of reasoning about environment variables.

What happens to n8n schedules when clocks fall back on November 1?

On November 1, 2026, at 2:00 AM, US clocks go back to 1:00 AM, so the hour from 1:00 to 1:59 happens twice. Here's what our simulated clock recorded in America/Chicago:

  • Daily at 1:30 AM: ran once, at the first 1:30 AM (CDT, 06:30 UTC). It didn't run again in the repeated hour. The next day it ran at 1:30 AM CST as expected.
  • Every hour at :15: ran at 1:15 AM CDT and 1:15 AM CST, one hour apart. That's correct by elapsed time, but your logs show two "1:15" runs.
  • Every 30 minutes: eight runs between 12:30 and 3:00 AM local time, evenly spaced every 30 minutes in real time, including both 1:00 and 1:30 runs twice.
  • Daily at 9:00 AM: ran at 9:00 AM local on October 31 (14:00 UTC) and 9:00 AM local on November 1 (15:00 UTC). The UTC time moved so the local time didn't.

Fall back is the easy one. Nothing gets skipped, daily jobs don't double up, and interval jobs keep a steady rhythm. The only risk is a downstream system that dedupes by local timestamp and sees two "1:15 AM" rows as a duplicate, or a report that sums "runs per hour" and shows a doubled 1 AM bucket.

What happens when clocks spring forward on March 14?

This is the one that bites. On March 14, 2027, at 2:00 AM, clocks jump to 3:00 AM, so 2:00 to 2:59 never exists. Same setup, same timezone:

  • Daily at 2:30 AM: didn't get skipped. It ran at 3:00 AM CDT instead, then went back to 2:30 AM the next day. Anything that expects "after the 2:30 export" to be true at 2:45 will be wrong that morning.
  • Every hour at :15: ran at 1:15 AM, then 3:00 AM, then 3:15 AM. That's an extra execution 15 minutes before the regular one. The library moved the missing 2:15 run to 3:00, and then the 3:15 run happened on schedule.
  • Every 30 minutes: ran at 1:30 AM, then 3:00 AM, 3:30 AM and on. The missing 2:00 and 2:30 runs were simply gone, which is fine for interval work.

The hourly double-fire is the real finding. If an hourly workflow sends a Slack digest, pulls a page of leads, charges usage or posts SMS, it does that twice within 15 minutes on spring-forward morning. Most of the time nobody's awake to notice. Then a client asks why their Monday report shows two syncs at 3 AM, or why a lead got two texts.

If your workflows already handle duplicate deliveries, this is a non-event. If they don't, the same idempotency patterns we use for duplicate webhook executions work here too: key the work on the data, not on the fact that the trigger fired.

How exposed was our own n8n instance?

We pulled every workflow from our own instance through the n8n public API on October 19, 2026 and counted Schedule Trigger and legacy Cron nodes:

  • 186 workflows, 45 with a schedule, 6 of those active.
  • Of the 6 active scheduled workflows, 5 had no workflow timezone set, so they depend entirely on the instance's GENERIC_TIMEZONE. One had it set explicitly.
  • Of the 45 scheduled workflows overall, 19 used a raw cron expression, 16 ran every N minutes, 11 ran daily and 7 ran every N hours.
  • One active workflow runs at 2:00 AM daily. Based on the test above, on March 14 it'll run at 3:00 AM.

None of that is broken, as long as the instance variable is right. But "five live schedules depend on one environment variable that nobody looks at" is exactly the kind of thing that breaks quietly during a server migration or a fresh Docker Compose file. When we move a client to a new host or upgrade a self-hosted instance, GENERIC_TIMEZONE is now on the checklist next to the encryption key.

How do you fix an n8n schedule that runs at the wrong time?

Work through it in this order.

Set GENERIC_TIMEZONE, not just TZ

In Docker Compose, add it next to your other n8n variables and restart:

environment:
  - GENERIC_TIMEZONE=America/Chicago
  - TZ=America/Chicago

Use an IANA name like America/Chicago or America/Mexico_City. Don't use CST or a fixed offset like -06:00. A fixed offset never observes daylight saving, so your schedule silently drifts an hour for half the year. On n8n Cloud, the instance timezone is set in the admin dashboard instead.

Set Timezone per workflow for client schedules

If you run workflows for clients in different zones, the instance default can only be right for some of them. Open Workflow settings → Timezone and set it for every schedule tied to someone's business hours. It overrides the instance value, as our test showed. This matters most on multi-tenant setups, where one instance can serve clients in Texas, California and Mexico.

Check the cron expression format

n8n accepts five-field cron (0 9 * * 1-5) and six-field cron with seconds first (0 0 9 * * 1-5). Adding or dropping a field shifts everything one place: 0 9 * * * means 9:00 AM daily, while 0 9 * * * * means minute 9 of every hour. Count the fields before you publish, and remember that a changed schedule only takes effect once you publish a new version of the workflow. The Schedule Trigger common issues page covers that and the other usual suspects.

Get nightly jobs out of the 1 to 3 AM window

If a job doesn't need to run at 2 AM, move it to 4 AM. That alone removes both DST edge cases. If it really does need the middle of the night (backups, warehouse syncs, cleanups), run it in UTC with a workflow-level Timezone of UTC. UTC never changes, so the job runs every 24 hours exactly. Just remember a UTC job lands at a different local hour in winter and summer.

Make hourly jobs safe to run twice

You can't move an hourly job out of the DST window, because it runs every hour. Make it idempotent instead: store the last processed ID or timestamp, or check whether the digest for that window was already sent. Pair that with real n8n error handling and monitoring so a schedule that silently stops shows up as an alert rather than a client complaint.

Should you just run everything in UTC?

No. UTC is the right answer for machines and the wrong answer for people.

  • Use UTC for backups, data syncs, cache warms, queue cleanup and anything measured in intervals.
  • Use the business's local timezone for reports, reminder texts, sales digests, appointment follow-ups and anything a human reads on their clock. A "9 AM" report scheduled in UTC arrives at 3 AM Dallas time in winter and 4 AM in summer, and a fixed offset like -05:00 is only right for half the year.

The pattern we use: instance GENERIC_TIMEZONE set to where the team works, explicit workflow Timezone on every client-facing schedule, UTC on infrastructure jobs, and nothing human-facing between 1 and 3 AM.

The short version

  • n8n uses workflow Timezone → GENERIC_TIMEZONE → America/New_York. The container TZ variable doesn't affect schedules.
  • Normal business-hour schedules follow local time correctly across DST.
  • Fall back (Nov 1, 2026): daily jobs run once, interval jobs run in both copies of the repeated hour.
  • Spring forward (Mar 14, 2027): a 2:30 AM daily job runs at 3:00 AM, and an hourly job fires an extra time at 3:00 AM.
  • Verify with the Timezone field in any Schedule Trigger execution. It tells you the truth in one click.

Get a free automation audit

Schedule bugs hide well. They don't throw errors; they just run at the wrong time, twice, or not when anyone expects. In an automation audit we pull every scheduled workflow from your n8n instance, check the timezone each one really runs in, flag the jobs that will move or double up at the next clock change, and fix the ones that touch clients. If you'd like us to look at yours before November 1, get a free automation audit or see how we build and maintain n8n workflow automation for agencies and service businesses.