WP-Cron Is Not Running, and What Quietly Breaks Because of It
WordPress has no scheduler of its own. It fakes one by checking for due tasks whenever someone visits the site. On a low-traffic site that means tasks run late or not at all, and the failures are silent.
The short version
- WP-Cron runs on page visits, not on a clock.
- A low-traffic site misses scheduled tasks routinely.
- A caching layer can prevent it running at all.
- The fix is a real server cron job, which takes five minutes.
What breaks when it stops
- Scheduled posts miss their schedule.
- Backups do not run.
- Update checks stop, so you stop seeing available updates.
- Transients never expire, so the options table grows.
- Email notifications and digests stop.
- Anything a plugin schedules — feeds, syncs, cleanups — stops.
None of these produce an error. That is what makes this worth checking proactively.
Confirm it is the problem
# list scheduled events
wp cron event list
# anything overdue?
wp cron event list --fields=hook,next_run_relative | head -20
# test the runner
wp cron test
Entries with a next run in the past are overdue. A few seconds late is normal; hours or days is not.
Why it fails
| Cause | How to tell |
|---|---|
| Low traffic | Few visits, tasks run very late |
| Page caching | Cached pages never execute PHP, so cron is never triggered |
| DISABLE_WP_CRON set with no replacement | Someone disabled it and never added a server cron |
| Loopback request blocked | A firewall or basic auth blocking the site calling itself |
| A stuck long-running task | One failing task blocks the queue behind it |
The loopback problem
WP-Cron works by the site making an HTTP request to itself. If HTTP authentication is enabled, or the server cannot resolve its own domain, that request fails silently. Test it:
curl -sI https://example.com/wp-cron.php?doing_wp_cron | head -3
You should get a 200. A 401 means basic authentication is blocking it — common on staging sites, where it is harmless, and occasionally left on in production, where it is not.
The proper fix: a real cron job
Disable the visit-triggered version and schedule it on the server instead:
// wp-config.php
define( 'DISABLE_WP_CRON', true );
# crontab -e — every five minutes
*/5 * * * * cd /path/to/wordpress && /usr/local/bin/wp cron event run --due-now --quiet
# or, if WP-CLI is not available
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
The WP-CLI version is better: it runs as a real process without a web-server timeout, and it bypasses any caching or authentication in front of the site.
Watch out
Setting DISABLE_WP_CRON without adding a server cron job stops scheduled tasks entirely. Always add the cron entry in the same session.
Clearing a stuck queue
One task that fatals every time it runs can block everything behind it:
# see what is scheduled
wp cron event list
# run a specific hook and watch for an error
wp cron event run some_stuck_hook
# remove a hook that should not be there
wp cron event delete some_stuck_hook
Hooks belonging to plugins you removed are a common cause. The plugin is gone, the schedule is not, and the hook fires into nothing.
Verify it is working
- Schedule a post five minutes ahead and confirm it publishes on time.
- Run
wp cron event listand check nothing is overdue. - Check your backup plugin’s log the next day.
Common questions
Does disabling WP-Cron make the site faster?
Marginally, by removing a check on each page load. The real reason to do it is reliability.
Every five minutes — is that too often?
No. The command exits immediately when nothing is due.
My host says they run cron for me
Verify it. Schedule a post and see whether it publishes on time.
Sumit
Writes everything on TechMozz.