How cron scheduling works¶
This page explains the scheduling mechanism used by Numera load workflows: why times are expressed in Europe/Berlin local time rather than UTC, how GitHub Actions handles DST transitions, and the reliability characteristics of scheduled triggers.
Why Europe/Berlin, not UTC¶
GitHub Actions cron schedules were historically UTC-only. This created a maintenance problem: German business hours are UTC+1 in winter (CET) and UTC+2 in summer (CEST). A workflow intended to run at "7 AM" would have to be manually adjusted twice a year to stay aligned with the working day, or it would drift by an hour after each DST transition.
In March 2026 GitHub added native timezone support for scheduled workflows. The timezone: field accepts any IANA timezone name alongside a cron: entry:
With this in place, all Numera load schedules are expressed in Europe/Berlin local time. GitHub converts to UTC internally, recalculating the offset at each DST boundary. No manual adjustment is needed when the clocks change.
CET and CEST¶
The Europe/Berlin timezone observes two offsets during the year:
| Period | Name | Offset from UTC | Example |
|---|---|---|---|
| Last Sunday in October → Last Sunday in March | CET (Central European Time) | UTC+1 | 02:00 CET = 01:00 UTC |
| Last Sunday in March → Last Sunday in October | CEST (Central European Summer Time) | UTC+2 | 02:00 CEST = 00:00 UTC |
A schedule written as 0 2 * * * with timezone: "Europe/Berlin" fires at 02:00 local time in both seasons. The UTC time at which GitHub actually runs the job shifts automatically — no workflow edit is required.
How GitHub evaluates the timezone field¶
When a workflow with a timezone-aware schedule is pushed to main, GitHub computes the UTC equivalent of the next firing time using the specified IANA timezone. At each DST transition GitHub re-evaluates the offset, so the schedule remains anchored to the local time rather than a fixed UTC offset.
During the "spring forward" transition (clocks jump from 02:00 to 03:00), any schedule landing in the skipped hour is moved forward to the next valid time. This is standard behaviour for DST-aware cron implementations.
Reliability characteristics of GitHub Actions scheduled triggers¶
Scheduled workflows in GitHub Actions are best-effort, not guaranteed:
- Delay: Runs typically start within a few minutes of the scheduled time but can be delayed by up to ~30 minutes when GitHub infrastructure is under load.
- Skipped runs: Occasionally a scheduled trigger is not fired, particularly for schedules that were recently added or modified. If the first one or two runs after a new schedule is pushed do not appear, this is expected behaviour — subsequent runs will be reliable.
- Default-branch only: Scheduled triggers are only evaluated against the
mainbranch. Changes to workflow files on feature branches have no effect until merged. - Inactivity disable: GitHub disables scheduled workflows if the repository has had no pushes to the default branch for 60 days.
These characteristics mean that Numera loads may start a few minutes late on occasion, and the very first run after a schedule change may be missed. The concurrency group (cancel-in-progress: false) ensures that if GitHub queues a run while another is in progress, the queued run will start as soon as the current one completes.
Concurrency and overlapping runs¶
Every scheduled Numera load workflow defines a concurrency group, for example:
cancel-in-progress: false means a new trigger does not kill a running job — it queues. This protects long-running loads from being interrupted by the next scheduled trigger, at the cost of potential start delays if runs regularly exceed the interval between triggers.