Why Your WordPress Scheduled Tasks Don't Run (and How to Fix WP-Cron)
WP-Cron is not cron — it only runs when somebody loads a page. On a quiet site that means backups, security updates and scheduled posts silently stop. Here is how to diagnose it and three ways to fix it.
By WP MegaManager Team
WP-Cron is not cron. It is a task queue that WordPress checks when somebody loads a page. No visitor, no check; no check, nothing scheduled runs. On a busy site the difference is invisible. On a brochure site, a staging copy, or a seasonal shop, it means scheduled work silently stops for hours or days at a time.
If you maintain sites for clients, this affects more of your portfolio than you think — the quiet sites are exactly the ones nobody notices have stopped working.
How WP-Cron actually works
wp_schedule_event() does not talk to the operating system. It writes an entry into the cron option in the database with a timestamp. On every front-end request, WordPress compares that timestamp to the current time and, if something is due, fires a second, non-blocking HTTP request back to itself at wp-cron.php to run the due jobs.
Three consequences follow:
| Property | Reality |
|---|---|
| Accuracy | "Every 5 minutes" means "on the first page load at least 5 minutes later" |
| On a site with no traffic | Nothing runs. Ever. |
| Under heavy traffic | Fires often, adding load — the opposite problem |
What silently stops on a quiet site
Everything in this list depends on WP-Cron by default:
- Scheduled posts — publish late, or not until someone visits
- Automatic core, plugin and theme updates — including security releases
- Backup plugin schedules — the nightly backup that never ran
- WooCommerce — scheduled sales, subscription renewals, abandoned-cart mail
- Transient cleanup — expired transients accumulate in
wp_options - Security scans and their alert mail
- Log rotation — files grow without limit
- Anything a management plugin schedules, including its own check-ins
The failure mode is the dangerous part: nothing errors. The site looks healthy. The work is simply not happening.
A site that goes 30 minutes without a visitor has already missed a 5-minute schedule five times. Overnight on a low-traffic site, that is 100+ missed runs.
How to tell whether it is happening
Check for scheduled events that are overdue. With WP-CLI:
wp cron event list
Any next_run_relative showing a negative time — "13 hours ago" — is an event that was due and has not fired. One overdue event is a hiccup. A screenful is a site whose cron has effectively stopped.
Check whether WP-Cron is disabled entirely. Look in wp-config.php for:
define('DISABLE_WP_CRON', true);
This line is correct only if a real system cron job was set up to replace it. It is frequently added by a host or a tutorial and left without the replacement, which stops scheduled work completely rather than making it unreliable.
Compare timestamps. If your backup plugin's "last run" is days old on a site whose schedule says daily, you have found it.
The three fixes
1. Real system cron (best, needs server access)
Disable the page-load trigger and let the operating system call the endpoint on a fixed schedule:
define('DISABLE_WP_CRON', true);
Then, in the server's crontab:
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null
Now the schedule is real, independent of traffic, and predictable under load. Most managed WordPress hosts offer this in their control panel.
2. External uptime pinger (works anywhere)
If you have no server access, any service that requests a URL on a schedule will do — including the free tier of most uptime monitors. Point it at https://example.com/wp-cron.php?doing_wp_cron every 5 or 15 minutes. It is less elegant than system cron but it removes the traffic dependency, which is the actual problem.
3. Push the work from outside (what a management platform should do)
The third approach inverts the relationship: rather than hoping the site runs its own schedule, an external system calls the site and tells it to do the work now.
This is strictly more reliable than the other two, because it does not depend on the site remembering to act — and it fails loudly. If the platform cannot reach the site, that is a monitoring signal in its own right, not silence that looks like health.
The monitoring trap this creates
There is a second-order problem worth naming, because most WordPress monitoring tools have it.
If a management platform decides a site is offline because the site stopped checking in, then every quiet site eventually gets reported as down. The check-in depends on WP-Cron; WP-Cron depends on visitors; so "no visitors" and "server on fire" produce an identical signal.
The correct behaviour is that silence triggers a question, not a verdict: the platform calls the site directly and lets the answer decide. A site that responds is fine, however quiet it has been. Only a site that fails to answer is actually down.
This is not theoretical — it is the difference between a monitoring system that cries wolf on every brochure site overnight and one you can trust at 3 a.m.
Frequently asked questions
Does disabling WP-Cron improve performance? Slightly, on high-traffic sites — you stop spawning a self-request on page loads. But only disable it if you replace it with a real cron job. Disabling it alone stops all scheduled work.
Why do my scheduled posts publish late? Almost always this. The post is due at 09:00; it publishes at the first page load after 09:00.
Is "missed schedule" the same problem?
Yes. WordPress marks a post future and missed when the cron event that should have published it never fired in time.
Do caching plugins make it worse? They can. A page served from a full-page cache may not bootstrap WordPress at all, so a cached visitor does not trigger the cron check. A heavily cached, low-traffic site is the worst case.
Where this leaves agencies
Per-site cron configuration does not scale — and the sites most affected are the ones you look at least often.
WP MegaManager does not rely on the site's cron for the work that matters. The platform pushes metrics collection, automatic updates and expiry of temporary access to each site on its own schedule, and treats a quiet site as a site to ask, not one to alarm about — it calls the site directly before ever reporting it as disconnected. Automatic updates started this way still obey each site's own policy, so a site with them switched off is left alone. See bulk updates and uptime monitoring.
Manage all your WordPress sites from one dashboard
Bulk updates, cloud backups, uptime monitoring, security and AI automation — in one place.
Start Free Beta