
WP-Cron Not Running? How to Tell — Before Your Customers Do
Stuck scheduled posts, skipped backups, renewals that never fired — WP-Cron fails silently because it only runs when someone visits. How to diagnose it in five minutes, fix it for good, and get paged when it breaks again.
WP-Cron Not Running? How to Tell — Before Your Customers Do
Scheduled posts stuck in the queue. Backups that quietly stopped last month. Abandoned-cart emails that never went out. WooCommerce subscriptions that didn't renew. Behind all of these is the same culprit: WP-Cron, WordPress's built-in scheduler, has stopped running — and nothing told you.
This guide explains how WP-Cron actually works (it's weirder than you think), the six ways it silently dies, how to diagnose it in five minutes, and how to make sure the next failure pages you instead of hiding for a month.
How WP-Cron actually works
Despite the name, WP-Cron is not cron. There is no clock. WordPress checks its list of due tasks only when someone visits your site. A visitor request comes in, WordPress notices "the backup was due 40 minutes ago," and fires it.
That design has a brutal corollary: no traffic, no cron. And its evil twin: the moment your site breaks, cron breaks too — the scheduler that might have alerted you dies with the patient.
Six ways WP-Cron silently stops
- Full-page caching. If Varnish, Cloudflare, or your host's cache serves pages without touching PHP, WordPress never wakes up. High-traffic sites can starve cron because of their caching.
DISABLE_WP_CRONset, real cron forgotten. A previous developer addeddefine('DISABLE_WP_CRON', true)towp-config.php— correct best practice — but the server-side cron job that was supposed to replace it never got created, or got lost in a host migration.- Loopback requests blocked. WP-Cron works by the site making an HTTP request to itself. Some hosts and security plugins block loopback requests. Site Health (Tools → Site Health) tells you if this is happening.
- Low traffic. A brochure site with 30 visits a day runs cron 30 times a day — at random hours. Anything scheduled overnight waits for the morning's first visitor.
- A fatal error inside a cron task. One broken plugin update can wedge the whole queue: every run starts, hits the fatal, dies, repeats.
- The site is simply down. Cron can't tell you the site is unreachable, because cron is part of the site.
Diagnose it in five minutes
- Install WP Crontrol (Tools → Cron Events). Look at the Next Run column. Times in the past that keep slipping mean the queue isn't executing.
- Or use WP-CLI:
wp cron event listshows the queue;wp cron event run --due-nowexecutes it and surfaces any fatal error directly. - Check Site Health for the "scheduled event has failed" and loopback warnings.
The fix: give WordPress a real clock
Best practice for any site that matters:
// wp-config.php — stop relying on visitors
define('DISABLE_WP_CRON', true);# Real system cron (host panel or crontab) — every 5 minutes
*/5 * * * * curl -s https://yourdomain.com/wp-cron.php?doing_wp_cron > /dev/nullMost hosts have a "cron jobs" panel that does this without SSH. Now scheduled tasks run on time, traffic or not.
The part that still isn't solved: who tells you when it breaks again?
Everything above fixes cron today. None of it tells you when the host migration, the security plugin, or next Tuesday's update breaks it again. The failure mode is silence — and you can't notice silence.
The answer is a dead-man's switch: your site checks in with an outside service on a schedule, and it's the absence of the check-in that raises the alarm.
The FlowAlert WordPress plugin does this with one toggle. It schedules a lightweight ping every 10 minutes through WP-Cron itself, to a monitor FlowAlert creates for the site automatically. If the pings stop, FlowAlert doesn't panic immediately — it first probes your site from the outside to see whether this is a real outage or just a quiet night on a low-traffic site. A site that answers HTTP but hasn't checked in for long enough gets flagged for what it usually is: WP-Cron starved or PHP broken behind a cache. A site that doesn't answer at all pages whoever's on call, immediately.
That distinction — site down vs. cron down vs. just quiet — is exactly the information you need at 7 a.m., and it's the difference between a monitoring tool and a false-alarm generator.
The checklist
- Site Health shows no loopback or scheduler warnings
-
DISABLE_WP_CRONis set and a real system cron exists (every 5 min) - WP Crontrol shows Next Run times in the future, not the past
- A dead-man's switch pings out every 10 minutes, with someone's phone on the other end
- The backup plugin's "last successful run" is from today, not from whenever cron died


