docs / concepts
Scheduled and recurring freezes
Build a recurring release window in the dashboard or through the API, and know which claim wins when a schedule and a manual freeze overlap.
complete · updated 1 september 2026
A schedule is a recurring or one-off freeze window defined in a real timezone. A Friday 17:00 → Monday 09:00 window ends at 09:00 local even when the clocks change in between, because the end of a window is a calendar offset on the wall clock rather than a duration in seconds. That distinction is the entire reason this feature is careful.
Scheduled and recurring freezes are in the free tier.
Build one in the dashboard
- Schedules → New schedule. Nothing is written until you save.
- Name and reason. The reason is copied onto every freeze the window creates, so write the one you want to read in the audit log in March. Eight characters minimum.
- Scope. Everything, a set of repositories, a glob, or named branches. The same picker the freeze composer uses.
- Timezone. An IANA name, defaulting to your organisation’s. This is the zone the wall clock below is read in, and it is the field that makes the DST rule work.
- Recurrence. Daily, weekly, monthly by date, or one-off. Weekly asks for days of the week; monthly asks for days of the month, where −1 means the last day.
- Start time, end time, end day. End day is calendar days after the start date: 0 for a window that closes the same evening, 3 for Friday to Monday.
- Read the panel on the right. It shows the next five occurrences in both the schedule’s timezone and yours, computed by the same code that will enqueue them, and it says when an occurrence crosses a daylight-saving change. Save stays disabled while those occurrences cannot be computed, because a schedule nobody can preview is a freeze nobody can predict.
The same schedule from the API
POST /v1/schedules. This is a Friday evening to Monday morning release freeze on every enabled repository’s default branch, in London time:
curl -X POST https://api.fwozen.com/v1/schedules \
-H "Authorization: Bearer $FWOZEN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Weekend release freeze",
"scope": { "kind": "org" },
"reason": "Weekend release freeze",
"timezone": "Europe/London",
"recurrence": "weekly",
"daysOfWeek": [5],
"startTimeLocal": "17:00",
"endTimeLocal": "09:00",
"endDayOffset": 3,
"reminders": [15]
}'daysOfWeek is ISO, so 1 is Monday and 5 is Friday. endDayOffset: 3 is what carries the window over the weekend, and reminders is minutes before it ends. POST /v1/schedules/preview takes the same body and answers with the occurrences without saving anything, which is what the panel in the dashboard calls. $FWOZEN_TOKEN is an API key with schedule:write, created at Settings → API keys.
What wins when two things overlap
Claims resolve by rank rather than by a priority number, and the first rank with a live claim wins: an exception on a pull request, then a manual freeze, then a thaw override, then a scheduled freeze, then open. So a manual freeze beats a schedule and beats a manual thaw, which is the fail-safe direction, and a thaw override cancels a scheduled window but only the freezes it names.
Behaviour folds across the whole winning set, restrictively. One live claim that blocks deploys blocks deploys, one that forbids exceptions forbids them, the branch thaws at the latest end among the winners, and a tie resolves toward freezing.
Skipping, running early, turning one off
- Skip next drops the next occurrence and leaves the schedule alone (
POST /v1/schedules/{id}/skip-next). - Run now starts the window early (
POST /v1/schedules/{id}/run-now). - Enabled off keeps the schedule and plans nothing.
- A freeze a schedule created is lifted like any other, from the freezes list. That ends the occurrence, not the schedule, and the next window still fires.