How do I know if my cron job actually ran?

The scary thing about a cron job isn't that it fails. It's that it fails and everything looks fine. No error in your inbox, no red mark anywhere — the backup just quietly stopped happening three weeks ago.
"Did my cron job run?" sounds like it should have a simple answer. It doesn't, because a job can fail in ways that leave no trace unless you set one up on purpose. Here's how to actually know.
Why a job fails without telling you
"It ran" hides at least four different outcomes, and only one of them is the good one:
- The scheduler never fired. The server was down, the platform disabled the job, or you hit a plan limit. Nothing ran, so nothing could report a failure.
- It ran and errored. The job started, threw halfway, and exited — but nobody was watching the exit code, so the error died in a log you never read.
- It "succeeded" and did nothing. Exit code zero, but it processed zero rows, or hit an empty result, or silently skipped the real work. Green, and useless.
- It hung. Still technically running hours later, holding a lock or waiting on a call that never returns. Not failed, not finished.
Every one of these looks identical from the outside — which is to say, it looks like nothing. That's the whole problem.
The checks that feel like enough but aren't
Reading logs works right up until you stop reading them, which is day two. A try/catch that emails you on error only fires if the code runs at all — useless for the case where the scheduler never fired. And "I'd notice if it broke" is exactly the assumption every silent failure depends on.
The fix: make success the thing you watch
Flip it around. Instead of waiting for a failure to announce itself, have the job announce its success — and watch for the absence of that.
The pattern is a heartbeat, sometimes called a dead man's switch. At the very end of the job, after the real work has actually finished, it sends one small ping to a URL. A monitor expects that ping on a schedule. Miss it, and the monitor alerts you.
- The job does its work.
- On success — and only on success — it pings the heartbeat URL.
- The monitor knows the schedule. If the expected ping doesn't arrive in time, it tells you.
This closes every case above at once. Scheduler never fired? No ping. Job errored before the end? No ping — because you only ping on success. Job hung past its window? No ping in time. The missing heartbeat is the alert.
Adding one is a few lines. Hand this to your AI tool and point it at the job:
Add a success heartbeat to my cron job so I can tell it actually finished, not just that it was scheduled. Requirements: - At the very end of the job — after all the real work has succeeded — send an HTTP GET or POST to a heartbeat URL I'll provide as an environment variable named HEARTBEAT_URL. - Only ping on success. If the job throws or exits non-zero, it must NOT send the ping, so a failed run is visible as a missing heartbeat. - Wrap the job body so any unhandled error is caught, logged with a clear message, and causes a non-zero exit before the ping line is reached. - Keep the heartbeat request short with a small timeout so a slow monitor can't hang my job. Show me the change for my job (tell me the language/runtime if you need it) and where the HEARTBEAT_URL goes.
Where the monitor comes from
You still need something on the other end of that ping — the piece that knows the schedule and notices silence. That's what Tell Me When Down does: it hands you a heartbeat URL, you ping it at the end of each run, and if a run goes missing you get an email within minutes.
It's the same idea that catches a keep-alive that GitHub quietly disabled — the job stops, the pings stop, and the silence is what pages you. If your jobs run on Vercel specifically, the Hobby-plan limits are their own way for a cron to never fire.
Stop trusting silence.
Join Tell Me When Down free, drop one heartbeat ping at the end of your job, and we'll watch for the run that doesn't come. A missed backup, a disabled scheduler, a job stuck for hours — you hear about it in minutes, not weeks.
spot something wrong or out of date? [email protected] — we'll fix it