Schedules & Exclusions
Multi-Schedule Support
Pipelines can define multiple schedule windows per day. Each schedule has its own evaluation cycle, lock, run log entry, and SLA deadline.
schedules:
- name: morning
after: "06:00"
deadline: "10:00"
timezone: America/New_York
- name: afternoon
after: "14:00"
deadline: "18:00"
timezone: America/New_YorkScheduleConfig Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Unique name within the pipeline (used as scheduleID) |
after | string | no | HH:MM — schedule becomes active after this time |
deadline | string | no | HH:MM — SLA deadline for this window |
timezone | string | no | IANA timezone (e.g. America/New_York); falls back to pipeline SLA timezone, then UTC |
Default Schedule
Pipelines without an explicit schedules list get an implicit default:
schedules:
- name: dailyThe daily schedule has no after time (always active) and no per-schedule deadline (uses pipeline-level SLA if set).
How Schedules Work
During each watcher tick (or Step Function execution):
ResolveSchedules()returns the configured schedules (or[{Name: "daily"}]if empty)- For each schedule,
IsScheduleActive()checks ifnow >= Afterin the schedule’s timezone - A separate lock is acquired per schedule:
eval:{pipelineID}:{scheduleID} - Run logs are keyed by
(pipelineID, date, scheduleID)— each schedule tracks independently - SLA deadlines prefer the schedule’s
deadlineover the pipeline’ssla.evaluationDeadline
Hourly Schedules
For pipelines that run every hour, define 24 schedules:
schedules:
- name: h00
after: "00:00"
deadline: "01:00"
- name: h01
after: "01:00"
deadline: "02:00"
# ... through h23The dedup key becomes {pipeline}:{date}:{scheduleID} (e.g. my-pipeline:2026-02-23:h14).
SLA Configuration
SLAs enforce time-based constraints. Breaching an SLA fires an alert but does not cancel the pipeline.
sla:
evaluationDeadline: "10:00"
completionDeadline: "12:00"
timezone: America/New_York
validationTimeout: "+45m"SLAConfig Fields
| Field | Type | Description |
|---|---|---|
evaluationDeadline | string | HH:MM — all traits must reach READY by this time |
completionDeadline | string | HH:MM — triggered job must finish by this time |
timezone | string | IANA timezone for deadline interpretation |
validationTimeout | string | Duration offset (e.g. +45m) — hard stop for evaluation |
Deadline Resolution
When a schedule defines its own deadline, that takes priority:
- Schedule deadline —
sched.Deadline(if set) - Pipeline evaluation SLA —
sla.evaluationDeadline(fallback)
The ParseSLADeadline() function converts an HH:MM string to an absolute time using the configured timezone and reference date.
Validation Timeout
Unlike SLA deadlines (which alert but continue), validationTimeout is a hard stop. If evaluation hasn’t completed within this offset from the schedule activation time, the Step Function transitions to a timeout state.
Calendar Exclusions
Pipelines can be excluded from running on specific days of the week or calendar dates. When excluded, the pipeline is completely dormant — no locks, no evaluation, no SLA alerts.
Inline Exclusions
exclusions:
days:
- saturday
- sunday
dates:
- "2026-12-25"
- "2026-01-01"Named Calendar Reference
Define reusable calendars in YAML files:
# calendars/holidays.yaml
name: holidays
days:
- saturday
- sunday
dates:
- "2026-12-25"
- "2026-01-01"
- "2026-07-04"Reference from a pipeline:
exclusions:
calendar: holidaysCombining Calendar + Inline
Inline days and dates are merged with the named calendar. A date or day matching any source triggers exclusion.
exclusions:
calendar: holidays # base exclusions
days:
- friday # additional inline exclusion
dates:
- "2026-03-15" # additional specific dateCalendar Configuration
Calendar YAML files are loaded from directories listed in calendarDirs:
calendarDirs:
- ./calendarsExclusion Evaluation
IsExcluded() checks in this order:
- Load the named calendar (if specified) from the registry
- Merge calendar
days+dateswith inlinedays+dates - Resolve timezone from
pipeline.SLA.Timezone(or UTC) - Compare current day-of-week (case-insensitive) against merged days
- Compare current date (
YYYY-MM-DD) against merged dates - If any match → pipeline is excluded for today
Active runs from a previous day are picked up on the next non-excluded day or via callback API.