Cron & heartbeat monitoring

The opposite of uptime monitoring: instead of us reaching out to your site, your job reaches out to us. Every time it runs, it pings a unique URL. If a ping does not arrive when it should, we know the job silently died — and we tell you.

  • Perfect for cron jobs, backups, data syncs and queue workers — the things that fail quietly
  • One line at the end of your script; nothing to install
  • Signal start, success and failure separately
  • Slack, Discord, Telegram and webhook alerts — free, not a paid tier
  • A status badge for your README

Because the ping comes to us, a single server is a genuine, honest listener — there is no probe network to fake. That is why this is the one kind of monitoring where one location is exactly right.

Create a heartbeat

We add a grace period, then alert if no ping has arrived.

Free · no card · or monitor a website instead

Drop it into anything

crontab

0 3 * * * backup.sh && \
curl -fsS https://goodping.com/hb/TOKEN

A shell script

curl -fsS https://goodping.com/hb/TOKEN/start
run_job || curl -fsS https://goodping.com/hb/TOKEN/fail
curl -fsS https://goodping.com/hb/TOKEN

GitHub Actions

- run: ./task.sh
- run: curl -fsS https://goodping.com/hb/TOKEN

Why heartbeat monitoring catches what uptime monitoring cannot

Uptime monitoring watches things that are supposed to answer — a website, an API. But the most damaging failures are silent: a nightly backup that stops running, a queue worker that dies, a sync job that quietly errors out. Nothing is "down" for a visitor to notice, and you find out weeks later when you need the backup that was never made.

A heartbeat flips the direction. Your job tells us "I ran" every time it completes. The moment it stops telling us — because it crashed, the server rebooted, cron broke, or the disk filled — the absence of a ping is the alert. You learn about a dead backup the next morning, not the day you need it.

Start, success and failure

Ping the plain URL on success. Add /start at the beginning of a run to measure how long it takes and catch jobs that begin but never finish. Add /fail when your script hits an error, so a job that runs but fails is treated as down even though it "ran".