Cron job heartbeat monitoring for indie SaaS
Cron jobs and background queues fail quietly: the web app stays green while nightly billing or email sync stopped three days ago. A heartbeat pattern means the job calls an HTTP endpoint after a successful run; silence past the expected window means something broke.
StillOnline runs scheduled HTTP GET checks on URLs you register — not a passive “missed ping” clock like Healthchecks.io. This guide shows how to adapt the heartbeat pattern with an HTTP health URL, when that is enough on Free (one URL, five-minute probes per pricing), and when to pair StillOnline with a cron-specific tool.
Quick answer
StillOnline does not ship a native “cron missed ping” monitor. Use an HTTP URL the job hits after success — for example GET /internal/cron-heartbeat returning 200 with a timestamp — and register that URL in StillOnline, or fold cron success into your main /health response. Probes run every five minutes on Free; two consecutive failures mark the check DOWN and trigger owner alerts. For sub-minute “job must run every hour” semantics, add a dedicated cron heartbeat SaaS or encode last-run time in a URL StillOnline already polls.
Heartbeat vs HTTP uptime vs CI checks
| Pattern | What fails | StillOnline fit |
|---|---|---|
| HTTP uptime | Web/API unreachable | Primary — GET /health every 5 min |
| Heartbeat | Job stopped running but server is up | Indirect — job must update a URL or health JSON |
| CI-only check | Deploy broke; prod might still serve 200 | GitHub Actions ≠ production cron — API checks |
Cron on Linux fires on schedule but does not tell you the script exited 0. Heartbeat closes that gap.
Pattern A — Dedicated heartbeat URL
- Add
GET /internal/cron-heartbeat(auth at edge or secret query param — never expose secrets in public docs). - On successful job completion, touch a file or DB row; the route returns 200 only if
last_successis within your SLA window (e.g. 26 hours for daily cron). - Register the HTTPS URL in StillOnline → HTTP check → expected 200.
curl -sS https://api.yourproduct.com/internal/cron-heartbeat
If the job fails, the route returns 503 or stale data — StillOnline goes red after two failed probes (~10 minutes on default interval).
Pattern B — Embed last-run in /health
Indie teams on Free (one URL) often add "cron_last_ok": "2026-06-08T06:00:00Z" to existing /health JSON and alert when parsing shows staleness — StillOnline still only checks HTTP status unless you return 503 when stale. Simpler: health handler returns 503 when now - last_run > threshold.
See health endpoint design and API-only monitoring.
Pattern C — Queue workers without a public port
Internal workers with no ingress cannot receive StillOnline GET directly. Options:
- Sidecar HTTP on the worker process (
:8081/healthbehind firewall is not probeable — you need a public URL). - Proxy metric: worker writes heartbeat to Redis/DB; your public
/healthreads it. - Separate component on the status page for “Background jobs” when web is up but queue is not — workers guide.
StillOnline setup
- Start free → new project.
- Add HTTP check on heartbeat or
/healthURL. - Status page + Telegram owner alerts on DOWN.
Pro ($9/mo) adds up to 10 URL checks per project — split web vs cron heartbeat if needed. See pricing.
Related guides
- Monitoring background workers and queues
- Health endpoint design
- Side-project production monitoring checklist
- API-only SaaS checks
FAQ
Does StillOnline support Healthchecks-style passive heartbeat URLs?
No. StillOnline actively GETs URLs on a schedule. Your cron must keep a reachable HTTPS endpoint in a success state, or your /health must flip to non-200 when jobs stall.
Can GitHub Actions replace StillOnline for cron monitoring?
Actions prove the workflow ran in CI; they do not replace external probes of production URLs customers use. Use both for different layers — GitHub Actions vs production.
How fast does StillOnline alert when a daily cron misses one run?
Default five-minute interval and two consecutive failures mean roughly 10 minutes after the URL stays unhealthy — not instant. Tune your heartbeat route to return 503 as soon as the SLA window passes.