type: decision
status: active
timestamp: 2026-06-20
tags: [monitoring, health-check, heartbeat, uptime, cron, decisions, architecture]

Health checks — split between healthchecks.io (cron heartbeats) and Better Stack (HTTP uptime)

Cron-job liveness verified by healthchecks.io \ heartbeat pings (dead-man-switch on 20 free checks), HTTP endpoint uptime is verified\ \ by Better Stack monitors (10 free monitors). Two distinct surfaces, two free tools,\ \ no overlap. Reinforces the auto-only-tracking rule \u2014 both verify auto-tracked\ \ surfaces without human polling."

Health checks — cron heartbeats + HTTP uptime, split

Decision

Health-check coverage is split across two free tools, picked by what they verify:

SurfaceToolModeFree tier
Cron-job liveness (did this run?)healthchecks.ioDead-man-switch heartbeat20 checks
HTTP endpoint uptime (is this URL serving?)Better StackActive probe (3-min interval)10 monitors

Both are adopted as of 2026-06-20. They don’t overlap: heartbeat verifies the runner ran, uptime verifies the URL responds. A silent cron failure produces no failed HTTP probe — only the heartbeat misses. A live URL responding 500s produces a heartbeat ping (the cron ran) — only the uptime probe fails.

Why both, not one

The user direction was: “BOTH — healthchecks.io + Better Stack heartbeats.”

Different failure modes:

Vendor-redundancy posture also helps: if Better Stack itself is the outage, healthchecks.io’s heartbeat miss can post directly to Instatus as a manual incident — same fallback path documented in the two-status-page redundancy strategy.

Implications

Cross-refs


Edit on GitHub · Back to index