Admins / Flow

How Daylight Saving Time Can Break Scheduled Flows in Salesforce

By Mariel Domingo

Twice a year, there’s a one-hour window where your Salesforce automation might quietly fail, and you won’t even notice until it affects something else downstream. 

Scheduled flows meant to do things outside active hours are usually scheduled around 2 AM. Maybe they’re meant to update records overnight, or prepare for the next business day. However, there’s an outstanding problem for regions that observe Daylight Saving Time: 2 AM doesn’t always exist.

What Actually Happens at 2 AM?

The issue comes down to Daylight Saving Time (DST). In regions that observe DST, the clock shifts twice a year:

  • Spring forward: the clocks skip ahead (1:59 AM to 3:00 AM)
  • Fall back: clocks repeat an hour (1:59 AM shifts back to 1:00 AM)

Now think about a scheduled flow configured to run at exactly 2:00 AM. During the spring forward, 2 AM technically does not exist. The flow, therefore, has no valid time to run. 

The fallback is a different story. You might expect 2 AM to run twice since the hour repeats, but according to Salesforce’s own documentation, scheduled jobs are stored and executed in GMT internally. 

The local clock display shifts around a fixed GMT anchor, so the job still fires once – it just appears to the user at a different local time before and after the transition. The spring skip, however, is a genuine risk that GMT anchoring doesn’t protect you from.

Scheduled Flows Are Vulnerable to DST

Anything scheduled always feels like a “set it and forget it” thing. It’s the reason why we’re scheduling things in the first place! It runs in the background, quietly doing its job while you’re focused on something else.

Scheduled flows rely on a lot of things under the hood. This includes the org’s time zone as well as a fixed execution time. However, that fixed execution time/schedule is endangered when your system clock shifts with DST. It becomes unstable because while the schedule is fixed, the time itself isn’t. But that reliability is built on the assumption that the clock is stable.

The distinction becomes clearer when you compare it to record-triggered flows. Those responds when something happening, like when a record is created, a field changes, or a condition is met. The trigger is an event, so it re-evaluates context every time. Scheduled flows don’t work that way, as they’re waiting for the clock to reach a specific moment. When that moment vanishes or suddenly occurs twice, the trigger itself becomes unreliable. 

This is also why Salesforce doesn’t throw an error when a scheduled flow skips during the transition. From the platform’s perspective, nothing went wrong. The flow technically didn’t fail, because the moment it was waiting for simply didn’t exist. This is exactly what makes it significantly harder to catch.

The Workarounds

There are a few approaches here, starting from the simplest.

1. Avoid 2 AM!

The quickest and cheapest fix! If your flow must run in the wee morning off-peak hours, schedule it at 1 AM or 3 AM instead. 

These times exist unambiguously on both DST transition days. 1 AM doesn’t solve the fall-back double-execution risk, but it eliminates the spring skip. If you’d like to avoid both, make sure to schedule for times before 1 AM and after 3 AM. Takes two minutes and requires no code, and could be good enough for low-stakes flows.

2. Build a DST-Aware Flow Trigger

You can build a compensating pattern involving a Platform Event–triggered flow that fires from an external scheduler that sends a Platform Event to Salesforce at the right UTC time. Your Salesforce Flow listens for that event rather than running on its own wall-clock schedule. 

If the external scheduler runs in UTC, Salesforce just reacts. Since the external scheduler runs in UTC, the DST problem never even enters the picture. This is definitely more complicated and involves more moving parts, but it keeps your logic declarative and in Flow.

3. Design a Monitoring Flow

And if you simply MUST schedule your flow at a DST-vulnerable time, a simple approach in creating a monitoring layer is to have a custom object (Flow_Health_Log__c for example) with a Last_Run__c datetime field. 

This acts as a “watchdog” so you know when it skips. Have your scheduled flow write a record to it and update that on every successful execution. Then schedule a separate flow at a non-DST-vulnerable time to check whether Last_Run__c is older than 25 hours. 

If it is, send an alert. You won’t prevent the skip, but you’ll at least know about it as soon as it happens, giving you enough time to devise a fix.

4. Use Scheduled Apex

Apex’s System.schedule() accepts a cron expression that runs in UTC internally, which means DST never touches it. For example:

String cronExp = '0 0 7 * * ?'; // 7 AM UTC daily
System.schedule('MyNightlyJob', cronExp, new MySchedulableClass());

For context, ‘0 0 7 * * ?’ is what controls the UTC offset math explicitly in this example, so the scheduler behaves identically every day of the year. Cron expressions follow a six-field format: Seconds, Minutes, Hours, Day-of-Month, Month, Day-of-Week

So ‘0 0 7 * * ?’ in this example breaks down as: second 0, minute 0, hour 7, every day of the month (*), every month (*), and ? for day-of-week (which is just a placeholder meaning “the date fields already define when this runs, don’t filter by day of week on top of that”). In plain English: run every day at exactly 7:00 AM UTC.

You can get as specific as needed. ‘20 30 8 10 2 ?’ as used in Salesforce’s example here would fire once a year, specifically February 10th at 8:30:20 AM. 

It’s also worth noting a behavioral difference for hourly automations, because hourly automations do not adjust for DST. It’s daily and higher-frequency schedules that do. So if you have flows or scheduled jobs on an hourly cadence, they’re operating on a different set of rules entirely.

Final Thoughts: The Broader Lesson

Scheduled automation in any platform has a hidden contract with the calendar. Most of the time, that contract is invisible, and everything works. Observance of DST comes with two days a year that are different. 

The safest general rule: any flow that must run reliably at a specific time, on a specific night, for a business-critical purpose should not be scheduled at 2 AM in a DST-observing time zone. Shift it, or move the scheduling logic to something that speaks UTC natively. Hopefully, this saves someone a post-mortem!

The Author

Mariel Domingo

Mariel is a Technical Content Writer at Salesforce Ben.

Leave a Reply