PostDeploy Start your 30-day free trial

Free cron job monitoring

Add one curl line to your cron job and PostDeploy alerts you when the job silently stops running. The trial includes 200 cron and heartbeat jobs with no credit card; they are separate from the 100 uptime monitors, so a scheduled job never uses one.

The PostDeploy Monitor console: fleet health with every monitor operational, a heartbeat monitor's daily pings and availability, and a TCP monitor's response-time chart.
The actual product, running an actual project. Not a mockup.

How to monitor a cron job with curl

Append a curl ping to the end of your cron command with && so it fires only when the job succeeds. If the ping does not arrive when PostDeploy expects it, you get an alert; that is the entire setup.

The && matters: it makes the ping conditional on the job's exit code, so a failing backup never reports success. The -fsS flags keep curl quiet on success and make it fail loudly on HTTP errors, which is what you want inside cron, where every byte of output becomes an email.

Each heartbeat monitor gets its own hb_ token when you create it in the console. The token is shown once, and possession of it is the authentication, so a bare URL works from any crontab without headers or API keys.

# Ping PostDeploy only if the job actually succeeded.
0 3 * * * /usr/local/bin/backup.sh && curl -fsS https://ingest.postdeploy.dev/h/hb_YOUR_TOKEN

Measuring how long the job took

Send one ping when the job starts and one when it finishes, and PostDeploy records the duration between them. Both pings go to the same heartbeat URL with a state query parameter added.

A plain ping with no state parameter is treated as a finish, so the one-liner from the first section keeps working unchanged. Duration tracking is useful the day a backup that normally takes four minutes starts taking forty: the job still "succeeds", but you can see it degrading before it falls over.

curl -fsS "https://ingest.postdeploy.dev/h/hb_YOUR_TOKEN?state=start"
/usr/local/bin/backup.sh
curl -fsS "https://ingest.postdeploy.dev/h/hb_YOUR_TOKEN?state=finish"

What a dead man's switch actually is

A dead man's switch is a check that alerts on the absence of a signal rather than on a failed request. Your job has to actively report in, and silence is treated as failure.

That inversion is what makes heartbeats catch the failures uptime checks structurally cannot: the server that was decommissioned with the crontab still on it, the typo that commented out a schedule line, the job that hangs forever and never exits, the container that stopped being scheduled. Nothing in those scenarios produces an error you could poll for; the only observable fact is that a ping stopped arriving.

Four places to put the ping

The same heartbeat URL works anywhere that can make an HTTPS request; GET and POST are treated identically.

Crontab: append the curl call after &&, as above.

systemd timer: with Type=oneshot, ExecStartPost runs only after the main command exits successfully.

GitHub Actions: keep the token in an Actions secret, and gate the step on the jobs before it.

Cloudflare Workers cron trigger: ping after the work completes, inside ctx.waitUntil so the scheduled handler can return.

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
ExecStartPost=/usr/bin/curl -fsS https://ingest.postdeploy.dev/h/hb_YOUR_TOKEN

Heartbeat monitoring vs uptime checks

A heartbeat is your job telling PostDeploy it ran; an uptime check is PostDeploy asking your URL whether it is alive. Heartbeats fit anything scheduled or headless, like cron jobs, queue workers and CI pipelines, while uptime checks fit anything with an endpoint, like an API, a site or a webhook receiver.

Most real projects need a few of each, so cron and heartbeat jobs have their own allowance, separate from uptime monitors, on every PostDeploy plan. Monitoring a scheduled job never uses an uptime monitor.

What each plan covers

Monitor, Observe (error tracking) and Measure (analytics) are all live on the same plan. The 30-day trial runs at Pro size: 200 cron jobs, 100 uptime monitors, 1-minute intervals and 30 days of detailed uptime samples. After the trial, Indie keeps 20 cron jobs, 20 uptime monitors, 5-minute intervals and 7 days of detailed samples for $5 a month; Pro and Scale raise every ceiling.

  • 200 cron and heartbeat jobs on the trial, separate from 100 uptime monitors
  • 1-minute minimum check interval on the trial
  • 30 days of detailed uptime samples on the trial
  • Email, Slack and Discord alerts included
  • No credit card for the 30 days

Questions

Do I need to install an agent to monitor cron jobs?

No. The monitoring is one outbound HTTPS request made by the job itself, so anything that can run curl, wget or fetch can ping a heartbeat.

Does the heartbeat URL need authentication?

No separate header or key: possession of the hb_ token in the URL is the authentication. Treat the URL like a secret and keep it in your crontab or CI secret store, not in a public repo.

Can I ping with wget or a plain HTTP library instead of curl?

Yes. GET and POST are accepted and treated identically, so wget, a fetch() call or any HTTP client works exactly the same as curl.

Is cron job monitoring included in the trial?

Yes. The trial includes 200 cron and heartbeat jobs, separate from its 100 uptime monitors, with 1-minute minimum intervals, no credit card required. Indie keeps 20 cron jobs after the trial.

Also running the other side of this? Read the related guide.

Ship your next project with one toolkit, not three.

Sign up and every feature described on this page is yours on the trial. No credit card.

Start your 30-day free trial