Schedule Boundaries¶
This guide covers edge cases and boundary conditions in schedule evaluation.
The daysOfWeek Execution Boundary¶
All executions — both hibernation and wakeup — are bounded to daysOfWeek. A day not listed in daysOfWeek is never an execution day. This means:
- Hibernation only starts on days listed in
daysOfWeek - Wakeup only triggers on days listed in
daysOfWeek - If a hibernation period would naturally end on a day not in
daysOfWeek, resources remain hibernated until the next listed day
Overnight Windows¶
When end is earlier than start, the window spans midnight:
offHours:
- start: "20:00" # 8 PM today
end: "06:00" # 6 AM next eligible day
daysOfWeek: ["MON", "TUE", "WED", "THU", "FRI"]
- Monday 20:00 → Tuesday 06:00 (Tuesday is in
daysOfWeek, wakeup proceeds) - Tuesday 20:00 → Wednesday 06:00 (Wednesday is in
daysOfWeek, wakeup proceeds) - Thursday 20:00 → Friday 06:00 (Friday is in
daysOfWeek, wakeup proceeds) - Friday 20:00 → Monday 06:00 (Saturday is not in
daysOfWeek, so wakeup does not trigger Saturday; resources stay hibernated through the weekend until Monday — the next listed day)
Day Boundaries¶
Friday Night with Weekday-Only Schedule¶
With daysOfWeek: ["MON", "TUE", "WED", "THU", "FRI"] and start: "20:00" / end: "06:00", Friday's hibernation at 20:00 does not wake up Saturday at 06:00. Saturday is not in daysOfWeek, so it is not an execution day. Resources remain hibernated through the entire weekend, and wakeup occurs at Monday 06:00.
To cover weekends explicitly with separate behavior (e.g., keep resources hibernated all day), add a weekend window:
offHours:
# Weeknight window
- start: "20:00"
end: "06:00"
daysOfWeek: ["MON", "TUE", "WED", "THU", "FRI"]
# Full weekend
- start: "00:00"
end: "23:59"
daysOfWeek: ["SAT", "SUN"]
With this configuration, the weekend window explicitly governs Saturday and Sunday execution. Without the weekend window, the weekday-only schedule simply keeps resources hibernated from Friday 20:00 through Monday 06:00.
Same-Day Windows¶
When start is before end, the window is contained within a single day:
offHours:
- start: "12:00"
end: "13:00" # Lunch break
daysOfWeek: ["MON", "TUE", "WED", "THU", "FRI"]
Timezone Handling¶
All schedule evaluation happens in the configured timezone:
- Daylight Saving Time: If the timezone observes DST, schedule windows shift accordingly. A 20:00 shutdown remains at 20:00 local time even when clocks change.
- UTC is recommended for environments spanning multiple timezones to avoid ambiguity.
Near-Midnight Boundaries¶
Windows near midnight require care:
# This window starts Monday 23:30 and ends at 00:30 on the next listed day
offHours:
- start: "23:30"
end: "00:30"
daysOfWeek: ["MON", "TUE"] # Monday 23:30 → Tuesday 00:30
Warning
If only ["MON"] were listed, the 00:30 wakeup would not trigger on Tuesday (since Tuesday is not listed). The resources would remain hibernated from Monday 23:30 all the way until the next Monday at 00:30 — a full week later. Ensure that both the hibernation start day and the expected wakeup day are included in daysOfWeek.
Execution Timing: Schedule Buffer and Safety Buffer¶
The controller intentionally delays every execution past the scheduled time by applying two buffers:
| Buffer | Default | Configurable | Purpose |
|---|---|---|---|
| Schedule buffer | 1 minute | Yes (--schedule-buffer-duration) |
Ensures the controller evaluates after the schedule boundary has passed |
| Safety buffer | 10 seconds | No (hardcoded) | Additional guard against clock-skew and race conditions |
Total offset: up to 1m 10s after the nominal schedule time (with default settings).
This means a start: "20:00" hibernation actually executes around 20:01:10, and an end: "06:00" wakeup executes around 06:01:10.
Why This Exists¶
The schedule buffer solves the narrow gap in full-day windows:
# Full-day shutdown — resources hibernate all day
offHours:
- start: "00:00"
end: "23:59"
daysOfWeek: ["SAT", "SUN"]
The gap between 23:59:00 and 00:00:00 is only 60 seconds. Without the buffer, the controller could evaluate at exactly 00:00:00 and race against the boundary. The 1-minute schedule buffer pushes evaluation to 00:01:00 (plus 10s safety buffer), well past the 00:00 start time.
The same applies to full-day wakeup windows:
# Full-day wakeup — resources stay awake all day
offHours:
- start: "23:59"
end: "00:00"
daysOfWeek: ["MON", "TUE", "WED", "THU", "FRI"]
Here the gap between 00:00:00 (end/wakeup) and 23:59:00 (start/hibernate) is even narrower in the other direction. The buffer ensures the wakeup at 00:00 executes cleanly at 00:01:10.
Adjusting the Schedule Buffer¶
The schedule buffer is configurable on the controller:
# Increase to 2 minutes (e.g., for slow API environments)
--schedule-buffer-duration="2m"
# Or via environment variable
SCHEDULE_BUFFER_DURATION=2m
The safety buffer (10s) is not configurable.
Note
If the controller restarts during a schedule window, it re-evaluates on startup and takes the appropriate action based on the current time and plan state.
Exception Interactions¶
When schedule exceptions are active, they modify the effective schedule:
- Extend: New windows are unioned with base windows (OR-logic)
- Suspend: Specified windows are carved out of the effective schedule
- Replace: Base schedule is completely ignored; only exception windows apply
These modifications affect all boundary calculations, including the daysOfWeek execution boundary. For example, a suspend exception that covers a Friday night window prevents the overnight hibernation even though the base schedule includes it. An extend exception that adds SAT to daysOfWeek would cause a Saturday 06:00 wakeup that would otherwise not occur.