---
title: "Scheduled task monitoring with heartbeats | Logdash"
description: "Monitor scheduled tasks with a heartbeat: the task proves it ran and silence sends a Telegram alert. A crontab to paste, and where Healthchecks.io fits better."
url: https://logdash.io/cron-monitoring/scheduled-tasks
---

# Scheduled task monitoring

Scheduled task monitoring means the task leaves proof after every clean run, whatever scheduler starts it, and a service outside the box alerts you when that proof gets older than the schedule allows.

A scheduled task fails in two ways. It runs and exits non-zero, or it never runs at all. The second one is the expensive kind: the server was rebuilt and the crontab did not come with it, the disk filled at 02:00, cron started the script with a PATH that has no node on it. Nothing crashes, so nothing reaches your error tracker. You find out when a customer asks why last week's invoices never went out.

## How to monitor scheduled tasks

Watch the outcome, not the scheduler. Every scheduler can run one more command only after a clean exit: && in a crontab, ExecStartPost= in a Type=oneshot systemd service, a last step in a CI job. Use that slot to touch a stamp file, after the work and never before it, and alert when the stamp gets too old.

## How Logdash decides a scheduled job is down

Logdash watches the stamp through a push monitor, which needs the Pro plan. On Pro it expects a ping in every 15-second window and alerts on the first empty one, with no per-job schedule or grace setting. One curl at the end of a nightly task would read as down almost all day. So a second crontab line pings every 5 seconds while the stamp is fresh.

 crontab -e 

```bash
# Once: mkdir -p /var/lib/heartbeat

# The task. The stamp moves only when the script exits 0.
0 3 * * * /srv/app/bin/send-invoices && touch /var/lib/heartbeat/send-invoices

# The heartbeat. Pings every 5 seconds while the stamp is under 25 hours old.
* * * * * for i in $(seq 12); do find /var/lib/heartbeat/send-invoices -mmin -1500 2>/dev/null | grep -q . && curl -fsS -m 4 -o /dev/null -X POST https://api.logdash.io/ping/68b4c1f0e3a2d5c7b9f01234; sleep 5; done
```

The -mmin -1500 is your schedule and grace period in one number. 1,500 minutes is 25 hours: a daily task plus an hour of slack before the stamp goes stale, the pings stop and the alert fires. A task that runs every 15 minutes wants something like -mmin -20\. The heartbeat line only reads the stamp, so it works unchanged behind a systemd timer. It also catches the box itself dying, because a dead cron sends nothing, and that alert lands within 30 seconds. One limit to plan around: the ping endpoint allows 300 requests a minute per IP and each heartbeat line sends 12, so one IP tops out at 25 of them.

## Scheduled task alert in three steps

1. **Create a push monitor** Add a service on Pro, set its monitor to push and copy the ping URL. A service holds one monitor, so each task gets its own service and its own name in the alert, up to 50 on Pro.
2. **Paste both lines** Add the task line and the heartbeat line to the crontab, then run the task once by hand so the stamp exists. Until it does the monitor reads down, which is correct: there is no proof yet.
3. **Let the stamp go stale** Connect a Telegram channel to the monitor, then backdate the stamp with touch -d '2 days ago' on Linux. Within 30 seconds Telegram shows the task's name, is down, status code 0 and Did not receive call for this time range. Touch it again and the is up message follows.

### Logdash vs Healthchecks.io for scheduled tasks

| Feature              | Logdash                                                  | Healthchecks.io                              |
| -------------------- | -------------------------------------------------------- | -------------------------------------------- |
| Schedule per task    | None, the find threshold in your crontab is the schedule | Period or cron expression, with time zone    |
| Failure signal       | Silence only                                             | Fail and exit-status endpoints alert at once |
| Whole host goes down | Alert within 30 seconds                                  | Alert after the period plus grace            |
| Alert channels       | Telegram and webhook                                     | Email, Slack, Telegram, webhooks and more    |
| HTTP uptime checks   | HTTP monitors on the same account                        | Not built, heartbeats only                   |
| Free plan            | No push monitors, Pro only                               | 20 checks                                    |
| Open source          | AGPL-3.0                                                 | Open source, self-hostable today             |

### When Healthchecks.io is the better pick

- Your tasks run on fixed schedules and you would rather type the cron expression once than encode it in a find threshold.
- You want the alert by email or Slack without building a bridge behind a webhook.
- You are not on Pro. Healthchecks.io watches 20 tasks for free, and Logdash push monitors start at Pro.
- You want the failing run's output in the alert. Healthchecks.io stores up to 100 kB of request body per ping. Logdash keeps only the fact that a ping arrived.

### What is scheduled task monitoring? 

Checking that a scheduled task actually ran and succeeded, by having it check in after every good run and alerting when the check-in stops. Error tracking cannot do this, because a task that never started throws nothing.

### Does scheduled job monitoring work for jobs that run once a day? 

Yes, with the stamp file above. Logdash checks a push monitor every 15 seconds, so a daily job cannot ping it directly. The job touches a file and a heartbeat line pings while the file is younger than your threshold. Healthchecks.io and Cronitor take a daily schedule directly, which is simpler if daily jobs are all you run.

### How do I monitor scheduled tasks without installing an agent? 

Use curl. The Logdash ping is a public POST to https://api.logdash.io/ping/<monitorId> with no auth header and no body, so cron, a systemd timer or a CI runner can all send it. A wrong id returns 404, and curl -f turns that into a non-zero exit you will see.

### Where does a scheduled task alert go? 

To Telegram or a webhook, the only two channels Logdash has. The Telegram message names the monitor and says it did not receive a call for this time range. A webhook set to POST receives the same facts as JSON. Email and Slack need a bridge you run behind the webhook.

## Keep reading

[All cron monitoring guides](https://logdash.io/cron-monitoring): One guide per scheduler, each with the code that proves a job ran and the alert for when it did not.

[Dead man's switch monitoring](https://logdash.io/cron-monitoring/dead-mans-switch): A dead man's switch alerts on the absence of a signal: the job checks in after every successful run, and when the check-ins stop, for any reason at all, the switch fires.

[Backup monitoring](https://logdash.io/cron-monitoring/backup-monitoring): Backup monitoring means hearing about a backup that did not finish, and AWS Backup and Azure Backup already alert on their own jobs, so the gap is the pg\_dump, restic and rsync scripts nothing watches.

[Restic backup monitoring](https://logdash.io/cron-monitoring/restic-backup): Chain restic backup, restic check and a timestamp so the stamp only moves when both commands exit 0, then let a heartbeat ping Logdash while the stamp is under 26 hours old, and a failed, partial or skipped backup becomes a Telegram alert.

[Uptime monitoring](https://logdash.io/features/monitoring): HTTP checks as often as every 15 seconds. When one fails, Telegram tells you before your users do.
