Docs / Schedules
Schedules
A schedule is a set of weekly windows in a time zone. Inside a window the deployment runs; outside it the deployment is stopped and keeps any retained disk and staged-weight storage charges. A business-hours schedule, 08:00 to 18:00 on weekdays, runs about 217 of the 730 hours in a month, a 70% cut in scheduled GPU hours before pre-warming, booting, draining or extra wakes. All day on weekdays is about 522 hours, a 29% cut. The cost calculator works both out for any model.
Set a schedule while deploying
In the deployment wizard, open Configuration and enable Schedule this deployment. Start with Office hours, Weekdays, all day, or Every night, then choose days and times. Add more windows for split shifts or different weekend hours. The time zone starts with your browser's zone and can be changed to any IANA time zone.
The weekly preview shows the running windows, hours per week and month, and the reduction from a 730-hour always-on month. Where an hourly rate is available, it also shows a window-only compute estimate. Overlapping windows count once. Pre-warm and other billable time, storage and the platform subscription are separate.
Review the schedule again on Confirm. Its time zone, windows and pre-warm setting are recorded with your consent. The schedule and deployment are queued together when you confirm.
The first deployment starts provisioning immediately, including outside a window. Once it becomes ready, the scheduler stops it outside its windows and pre-warms future wakes. A schedule is not a delayed first launch. The budget cap still applies, and the deletion timer counts accumulated serving time across wakes. Turn the timer off in Configuration if you want a recurring service without timed deletion.
For an existing deployment, open its Overview tab and find Wake/sleep schedule to set or edit the windows, even while the first deployment is still booting. Saving applies the new windows immediately, so an endpoint outside its new windows may stop. Removing the schedule leaves the deployment in its current state; it does not automatically resume it.
Windows and time zones
Each window is a start and an end time on one or more weekdays, in the schedule's IANA time zone. Windows follow the zone's clock through daylight-saving changes: an 08:00 start is 08:00 local on both sides of the change, and a window that would fall into a skipped hour starts at the first valid minute after it. A time repeated when clocks go back uses its later occurrence, once. Windows that touch or overlap are merged. In the editor, an end earlier than its start means the following day; selected weekdays are the start days. Midnight is displayed as 24:00.
The API uses numeric weekdays: 0 is Monday and 6 is Sunday. Each
API window stays within one day, with 24:00 allowed as its end.
The editor splits overnight spans automatically. API clients should send,
for example, Monday 22:00 to 24:00 and Tuesday 00:00 to 06:00 as two rows.
curl -X PUT https://app.llmhangar.com/v1/deployments/$ID/schedule \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"timezone": "Europe/Amsterdam",
"windows": [
{ "days": [0, 1, 2, 3, 4], "start": "08:00", "end": "18:00" }
],
"prewarm_override_minutes": 20
}'
The response echoes the canonical windows, the hours per month and the savings percentage, and the next boundary. Every edit is audited and re-resolves any override that expires at a boundary.
To configure a schedule during deployment through the API, pass the
same object as schedule to both
POST /v1/deployments/preview and
POST /v1/deployments. Preview returns it in
summary.schedule; draft creation saves it without starting
automation. Confirm the deployment with the preview's summary hash to
activate both. Omitting schedule leaves scheduling off.
Pre-warm
The schedule starts the instance ahead of each window by a lead
time to give the endpoint time to become ready before the window opens. Capacity or startup delays can still make it late. The
lead is your prewarm_override_minutes when set; otherwise, once
three resumes have been measured, their p90 plus a margin; until then
the larger of 20 minutes and 1.25 times the catalog's cold-boot
estimate. It is clamped between 5 minutes and 6 hours and shown on the
deployment with its provenance: estimate, measured or set by hand.
Enter 1 to 360 whole minutes, or leave it blank (API: null or 0) for
automatic. The editor preserves your entered value even when the minimum
effective lead raises it to five minutes. A lead above 45 minutes shows an
advisory; an automatic estimate above six hours is capped and marked
best-effort.
On the default node-local placement the deployment serves as soon
as it is ready, which can be a few minutes before the window. On a
hosted or private edge placement it is gated: ready but not exposed,
answering 503 with the window start as next_start, and
opens at the boundary. A start that runs late is reported as a
started_late event, and a deployment that could not start
at all parks stopped with a hold that says why.
Overrides: holds and wakes
Anything that moves a scheduled deployment out of its schedule is an override with a reason, an author and an expiry, listed on the deployment and in the API.
- Manual hold. A stop by hand. No expiry: the schedule will not wake the deployment until you resume it.
- Idle hold. Idle autostop stopped it. Clears at the next schedule boundary, or on a manual resume.
- Budget hold. The budget cap or the monthly budget stopped it. Clears only when the cap is raised or the month resets; a schedule or a wake never starts a held deployment.
- System hold. The platform parked it: no capacity inside the allowance, a refused provision, a failed spot recovery. Clears by the audited retry action.
- Wake. A start outside the window, by your request or by wake-on-request. Runs until the next boundary and never outranks a hold.
# List live and past overrides
curl https://app.llmhangar.com/v1/deployments/$ID/overrides -H "Authorization: Bearer $TOKEN"
# Clear one (manual, idle and wake overrides; system holds need a reason)
curl -X POST https://app.llmhangar.com/v1/deployments/$ID/overrides/$OID/clear \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"reason": "capacity is back"}'
Webhooks
Lifecycle events are delivered to the endpoints you register:
deployment.stopped, deployment.resumed,
deployment.stop_failed, deployment.start_failed,
deployment.started_late, deployment.fell_back,
deployment.evicted and deployment.recovered.
Endpoints must be public https URLs; deliveries retry with backoff and
each attempt is listed with its response code.
POST https://hooks.example.com/llmd
X-LLMD-Delivery: 7f3a9c2e-...
X-LLMD-Signature: t=1756800000,v1=5d41402abc4b2a76b9719d911017c592...
Content-Type: application/json
{ "id": "7f3a9c2e-...", "type": "deployment.stopped", "created_at": "2026-09-02T16:00:04Z",
"deployment_id": "9c1e0b0e-...", "data": { "reason": "stopped on request or by schedule" } }
# Verify (Python)
import hmac, hashlib, time
t, v1 = dict(p.split("=") for p in sig.split(",")).values()
expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
assert hmac.compare_digest(expected, v1) and time.time() - int(t) < 300
The delivery id is the deduplication key: a retry after a timeout
carries the same id. Endpoints and their secrets are managed under
Settings, Webhooks, or at /v1/webhooks.