WordPress Cron Monitoring: ‘Running’ and ‘Working’ Are Different

We’ve covered separately why WP-Cron’s default, visitor-triggered behavior causes scheduled posts to publish late on low-traffic sites — the fix there was disabling the default and running a real server or external cron against wp-cron.php on a fixed schedule. But getting cron to fire reliably and confirming a job actually worked are two separate problems, and most setups only solve the first one.

Why a Simple Uptime Check Doesn’t Catch This

An uptime monitor confirms your site responds to a request — it says nothing about whether a specific scheduled job inside that request actually did anything useful. A cron endpoint can return a clean 200 OK status while silently failing internally: a partial failure, a gradually degrading process, or a job that’s technically executing but not actually completing its real work. Uptime checks structurally can’t distinguish “the site is up” from “the thing that was supposed to happen actually happened.”

The Heartbeat Pattern

The practical fix: have each scheduled job write a timestamp to a WordPress option (or equivalent storage) every time it successfully completes — a “heartbeat.” Then separately, have an external monitoring service poll a small, dedicated endpoint that returns that stored timestamp, and alert you specifically when the timestamp goes stale (hasn’t updated within the expected interval). This structurally closes the gap: the site being reachable and the job having genuinely run successfully are now two independently verifiable facts, not one assumed from the other.

What to Actually Set Up

Layer What it checks Tooling
Reliable cron triggering Ensures cron actually fires on schedule, not just on a visitor’s page load DISABLE_WP_CRON plus a real server cron or external service hitting wp-cron.php every 1–5 minutes
Site availability Confirms the site is reachable at all A standard external uptime monitor
Job health (the heartbeat) Confirms the specific scheduled job actually completed its work, not just that a request returned 200 A heartbeat timestamp option, polled by an external service against a dedicated endpoint

What to Actually Do

  1. Confirm WP-Cron is disabled in favor of a real external trigger, as covered in our earlier piece on this — this is the prerequisite layer, not the full solution on its own.
  2. Add a heartbeat timestamp to your most business-critical scheduled tasks specifically — order processing jobs, subscription renewal checks, anything where silent failure has real consequences, not every minor scheduled task equally.
  3. Set up external monitoring against the heartbeat endpoint, separate from your general site uptime monitor, with alerting tuned to each specific job’s expected run frequency.
  4. Treat a stale heartbeat as an actual incident, not a false alarm to dismiss — the entire point of this pattern is surfacing exactly the silent-failure case that a working site and a green uptime check would otherwise hide.

This extends Why Your Scheduled WordPress Posts Publish Late (and How to Fix It). Want critical scheduled tasks on your site monitored properly? Get in touch.

Frequently Asked Questions

Is a heartbeat check necessary for every scheduled task on a site?

No — it’s most valuable for business-critical jobs where silent failure has real consequences (orders, subscriptions, data syncs); applying it to every minor scheduled task adds monitoring overhead without proportional benefit.

Does fixing WP-Cron’s triggering mechanism make heartbeat monitoring unnecessary?

No — they solve different problems. Reliable triggering ensures the job’s code actually runs on schedule; heartbeat monitoring confirms that run actually completed its intended work, which a triggering fix alone doesn’t guarantee.

What’s a reasonable external service to use for this kind of monitoring?

Several options work — UptimeRobot, Better Stack, cron-job.org, or even a simple scheduled shell script — the specific tool matters less than having an external check independent of the site itself, so a site-wide outage doesn’t also silence your own monitoring.

Featured image: original illustration.


Ready to start your project?

Share your brief and we’ll propose the right approach — a full site, a landing page, or a custom plugin.