Check statuses & lifecycle
A heartbeat check has five statuses. Understanding the transitions explains exactly when an alert arrives — and why sometimes it (correctly) doesn't.
| Status | Meaning | Alerts |
|---|---|---|
| new | the check exists, no ping has arrived yet | none |
| up | pings arrive on time | the up event on recovery after down |
| late | the deadline (+ up to 30 s of slack) was missed, the grace period is running | the late event (if enabled) |
| down | grace expired, or the job explicitly reported failure | the down event + reminders |
| paused | monitoring switched off manually | none |
Why new never alerts
A check in the new status is not tracked by the scheduler: it has no deadline yet — one appears only with the first ping. So you can create checks for future jobs in advance (or roll the config out with a deploy): until the code ships and pings, there are no false downs. The first successful ping flips the check to up and sets the first deadline.
The deadline: period and cron
The deadline is the moment the next ping is due. It is computed from the actual time of the last ping:
- period — last ping +
period_sec. The schedule "floats": a job that starts with drift does not accumulate error; - cron — the next run of the cron expression in the check's timezone after the last ping. DST transitions are handled by the timezone;
- OnCalendar — like cron, using a systemd expression.
Grace
Grace is the allowance after the deadline — insurance against
schedule jitter and long runs: cron rarely fires to the second.
The check becomes late not at the very second of the
deadline but after a small slack —
deadline + min(grace, 30 s):
otherwise the minute-precision scheduler would outrun a ping
arriving a second behind schedule, and minute-level cron jobs
would blink up↔late. The slack never moves the down
moment — that stays at
deadline + grace_sec:
up ──(deadline + min(grace, 30 s))──▶ late ──(deadline + grace)──▶ down ▲ │ └──────────────── any successful ping ◀───────────────┘
With grace = 30 s the late window collapses: the late threshold coincides with the down moment and the check goes straight to down. Grace is set per check: 30 seconds to 30 days — anything shorter would turn the few seconds of jitter every scheduler has into false down alerts. Time-based transitions are executed by the scheduler with minute precision. The down alert arrives within ~1–2 minutes of grace running out: the overdue check is found by the minute-precision scheduler, the delivery itself takes seconds.
Instant down
An explicit failure signal bypasses grace: a ping to
/<uuid>/fail or with a
non-zero exit code (/<uuid>/42)
flips the check to down immediately — the job itself said
it failed, there is nothing to wait for.
Recovery, pause and reset
- from late and down the check returns to up with the very next successful ping. The "up" alert goes out only when recovering after down; a late → up transition is just a slightly delayed ping — no alert, nothing in the delivery journal;
- paused — a manual pause: pings don't change the status, deadlines aren't tracked, no alerts. For HTTP checks paused means "don't probe";
- reset (the "Reset" button on the check page) returns the check to new, as if it had just been created: the last ping, duration and deadline are cleared. The ping and flip history is kept — the reset itself shows up in the timeline as its own event. Counting starts over with the first ping; handy after a long idle spell or when a job moves.
Unstable checks (flap damping)
A check that keeps bouncing between up and down ("flapping") can send dozens of identical alerts within an hour. CronAlive dampens that storm automatically:
- alertable status changes — down and the down → up recovery — are counted in a sliding 1-hour window;
- on the 6th change within an hour a single "check is unstable: N status changes in an hour, alerts paused" alert goes out instead of the regular one — to every channel subscribed to down events;
- further down/up alerts are suppressed but journaled: the delivery journal shows them as
suppressedwith the reason "the check is unstable (flap damping)" — it is always clear why things went quiet; - the check page shows an amber "unstable" badge next to the status;
- after 30 minutes without a single status change a "has stabilized, current status: …" alert arrives — it states since when the alerts had been paused — and regular alerting resumes.
late alerts neither move the threshold nor get suppressed — they are an early signal. Manual operations (pause, resume, reset) do not count as flips. Defaults: threshold 6 changes, window 1 hour, 30 minutes of silence to exit.
Pause, resume, delete and tag assignment also work in bulk — tick the checkboxes in the list. From the check page you can clone a check (config without history) and move it to another project of the account.
Statuses are visible on the dashboard, in the API and on public badges; HTTP checks use K confirmations instead of ping timing.