Schedules
A schedule is the top-level definition in Wakeplane. It combines a cadence (cron, interval, once), a target (what to run), and policies (how to behave on overlap, misfire, failure).
YAML manifest shape
Section titled “YAML manifest shape”Schedules can be created from a YAML file using wakeplane schedule create -f <file> or via POST /v1/schedules with a JSON body.
name: nightly-sync # required, unique identifier for displayenabled: true # set false to create pausedtimezone: America/Los_Angeles
schedule: kind: cron # cron | interval | once expr: "0 2 * * *" # for cron: standard 5-field cron expression
target: kind: workflow # http | shell | workflow workflow_id: sync.customers input: source: crm
policy: overlap: forbid # allow | forbid | queue_latest | replace misfire: run_once_if_late # skip | run_once_if_late | catch_up timeout_seconds: 900 max_concurrency: 1
retry: max_attempts: 5 strategy: exponential initial_delay_seconds: 30 max_delay_seconds: 900Schedule kinds
Section titled “Schedule kinds”Uses a standard 5-field cron expression (minute, hour, day-of-month, month, day-of-week). The next occurrence is computed using the schedule’s timezone.
schedule: kind: cron expr: "0 2 * * *" # 2am dailyschedule: kind: cron expr: "*/15 * * * *" # every 15 minutesinterval
Section titled “interval”Fires every N seconds on a fixed cadence. The anchor is schedule.anchor_at when supplied, otherwise start_at, otherwise the schedule’s creation time. Restart and resume compute the next slot on that cadence rather than shifting the anchor to the current time.
schedule: kind: interval every_seconds: 300 # every 5 minutesFires once at a specific time.
schedule: kind: once at: "2026-06-01T09:00:00-07:00"schedule.at is an absolute timestamp. Provide a full RFC3339 value with offset. If you want “9am Los Angeles time”, encode that offset in the timestamp itself.
After the occurrence is materialized, next_run_at becomes nil. The schedule is not automatically rewritten to enabled=false; it simply has no next occurrence left to materialize.
Timezone behavior
Section titled “Timezone behavior”Every schedule requires an explicit timezone field (IANA timezone string, e.g. America/Los_Angeles, UTC, Europe/Berlin). Empty values and the host-dependent Local value are rejected.
- Cron expressions are evaluated in the schedule’s timezone.
- The
once.attimestamp is stored as an absolute instant; include the intended offset in the value. - Interval schedules use UTC internally; timezone affects only display.
- All
next_run_atvalues stored in the database are UTC.
DST transitions: Cron times in a spring-forward gap are skipped. During fall-back, a repeated local clock time can produce two occurrences at distinct UTC instants. For example, 30 1 * * * in America/Los_Angeles fires at both 08:30Z and 09:30Z on November 1, 2026. Each instant has its own occurrence identity.
Pause and resume
Section titled “Pause and resume”wakeplane schedule pause <id>wakeplane schedule resume <id>Or via HTTP:
POST /v1/schedules/{id}/pausePOST /v1/schedules/{id}/resumePause sets enabled=false and records paused_at. The planner stops materializing new occurrences. Existing pending or running runs are not affected.
Resume sets enabled=true, clears paused_at, and recomputes next_run_at from the current time. It does not catch up occurrences missed while paused. Misfire policy applies when an enabled schedule’s persisted next occurrence becomes overdue.
Trigger-now
Section titled “Trigger-now”wakeplane schedule trigger <id>Creates a manual run immediately. The normal schedule cadence is unaffected - next_run_at is not changed. The manual run has a manual:{run_id} occurrence key separate from any scheduled occurrences.
Trigger requires a reason:
# via HTTPPOST /v1/schedules/{id}/trigger{"reason": "manual smoke test"}Full replacement vs partial update
Section titled “Full replacement vs partial update”PUT /v1/schedules/{id}- replace the complete schedule definition, preserving its ID, creation time, and run history. Omitted optional fields return to their defaults; omittedenabledcreates a paused definition. Supply the required name, timezone, schedule, and typed target.PATCH /v1/schedules/{id}- partial update. Only provided fields change. Useful for togglingenabledor updating a target URL.
Target kinds
Section titled “Target kinds”See Executors for full executor details. Brief reference:
| Kind | Required fields | Optional fields |
|---|---|---|
http | url, method | headers, body, http_job |
shell | command | args |
workflow | workflow_id | input |
Timeout and concurrency are controlled by policy.timeout_seconds and policy.max_concurrency, not by target-specific fields.
http_job selects tracked remote execution and requires method: POST. Its optional settings are poll_interval_seconds (default 5, allowed 1–300) and a same-origin lookup_url for recovery by submission key. overlap: replace is rejected for this mode. See Automation for the runner contract.
Default policy values
Section titled “Default policy values”When policy or retry fields are omitted, these defaults apply:
{ "policy": { "overlap": "forbid", "misfire": "run_once_if_late", "timeout_seconds": 300, "max_concurrency": 1 }, "retry": { "max_attempts": 0, "strategy": "exponential", "initial_delay_seconds": 30, "max_delay_seconds": 900 }}max_attempts counts total attempts including the first. Values 0 and 1 do not schedule another attempt. Use strategy: exponential with max_attempts greater than 1 to allow retries; strategy: none disables them.
See Policies for full policy semantics.