
Why WP-Cron misses tasks
WordPress has no background process of its own. On each page load it checks whether any scheduled task is due and, if so, starts it. On a busy site that works. On a quiet site, or one where a page cache answers most visits before WordPress runs, due tasks wait until the next uncached visit. Share count refreshes, scheduled posts, backups and email digests all depend on this. The old post on this domain about using external cron jobs was written because share counts stopped updating for exactly this reason.
A worked example with numbers
The figures are invented to show the arithmetic. A small magazine gets 400 page views a day. A page cache serves 97 percent of them, so WordPress itself runs for about 12 requests a day, and those cluster around the two times the editor logs in. A share plugin schedules its count refresh every five minutes, which was the old plugin's default "Cache expiration", and a backup plugin schedules a nightly export at 03:00.
With WP-Cron alone, the refresh runs at most 12 times a day, at whatever moment a request happens to arrive, so counts on the homepage are between one and fourteen hours old. The nightly backup runs at 03:00 only if someone hits an uncached page after 03:00, so it runs at 09:15 when the editor logs in, during business traffic. With a server cron job every ten minutes, WordPress is called 144 times a day at fixed times: the count refresh is never more than ten minutes late and the backup starts within ten minutes of 03:00. The cost is 144 short requests a day, which even a small host tolerates. The two lines that make the change are these.
// wp-config.php, above the line that says to stop editing
define( 'DISABLE_WP_CRON', true );
# crontab -e: every 10 minutes, quietly
*/10 * * * * curl -s -o /dev/null https://example.com/wp-cron.php?doing_wp_cronThen confirm the schedule moves. The listing below is what a healthy site shows a few minutes after the first cron run: every next-run time is in the future and the share refresh hook has a short interval.
$ wp cron event list --fields=hook,next_run_relative,recurrence
+------------------------------+------------------+------------+
| hook | next_run_relative| recurrence |
+------------------------------+------------------+------------+
| example_share_refresh | 3 minutes | 5 minutes |
| example_backup_nightly | 9 hours 40 min | 1 day |
| wp_version_check | 6 hours | 12 hours |
+------------------------------+------------------+------------+Set up a real cron job
Disable the visit trigger
Add
define( 'DISABLE_WP_CRON', true );towp-config.php, above the line that says to stop editing.Choose a schedule
Every 5 to 15 minutes suits most sites. More often wastes resources.
Add the job
In your host's cron panel or crontab, call the cron endpoint or WP-CLI (examples below).
Verify
Run
wp cron event listand confirm the next run times move forward.
# crontab: call wp-cron.php every 15 minutes
*/15 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
# or, with shell access, use WP-CLI
*/15 * * * * cd /path/to/site && wp cron event run --due-now > /dev/null 2>&1Choosing between the two
| Method | Pros | Cons |
|---|---|---|
| HTTP call to wp-cron.php | Works on any host with a cron panel | Goes through the web server and its timeouts |
| WP-CLI on the server | No web timeouts, runs as a process | Needs shell access and WP-CLI |
| Host's built-in scheduler | No setup | Check the interval it uses |
Check tasks are healthy
wp cron event listshows every scheduled hook and when it next runs.- Hooks with next-run times in the past mean cron is not running.
- Site Health in the dashboard warns when scheduled events are late.
Symptoms, causes and fixes
| Symptom | Cause | Fix |
|---|---|---|
| Scheduled posts show "Missed schedule" | No request reached WordPress at publish time | Add a server cron job; the post publishes on the next run |
| Share counts stale for days | The refresh hook waits for an uncached visit | Server cron every 5 to 15 minutes; see share counts not updating |
| Next-run times in the past after adding cron | DISABLE_WP_CRON is set but the job never fires | Check the crontab saved, the URL is right, and the firewall allows it |
| Job runs but tasks still late | The HTTP call times out before long tasks finish | Switch to WP-CLI, or raise the timeout on the curl call |
| Two runs overlap and duplicate emails | Interval shorter than the longest task | Lengthen the interval, or use WP-CLI which waits for completion |
| Site Health reports a loopback error | The server cannot request its own address | Use WP-CLI, which needs no loopback |
Pitfalls with a WordPress cron job
- Placing the constant below the "stop editing" line in
wp-config.php. Constants defined there are read too late. Put it above. - Forgetting
?doing_wp_cronon the URL. Without it, a page cache or the cron lock may answer the request without running tasks. - Running the job as a user who cannot read the site. WP-CLI needs the same PHP version and file permissions as the web server; a job that runs as root creates files the web server cannot later overwrite.
- Setting a one-minute interval. Most hooks recur every five minutes or longer, so extra runs only add load, and a long task can overlap the next run.
- Leaving
ALTERNATE_WP_CRONon from an old fix. It redirects visitors to trigger cron and is unnecessary once a real job exists. - Assuming the host's scheduler calls WordPress. Some call a file path with PHP directly, which loads nothing; check its command.
Once the schedule is reliable, the remaining share count problems are almost always tokens or caching, which the share counts section covers. Before blaming a plugin for anything else, work through the plugin troubleshooting order, and if an update has started raising deprecation notices, fixing the get_currentuserinfo() is deprecated notice shows the pattern. All three sit in the WordPress troubleshooting notes.
Sources
- WordPress Plugin Handbook: Cron
- WordPress Plugin Handbook: hooking WP-Cron into the system task scheduler
- WP-CLI command reference: wp cron
- WordPress Advanced Administration Handbook: editing wp-config.php
Questions
Should I disable WP-Cron?
On low-traffic or heavily cached sites, yes, as long as you replace it with a real cron job.
How often should WordPress cron run?
Every 5 to 15 minutes is enough for most sites.
How do I know cron is working?
Run wp cron event list and check that next-run times are in the future and advancing.
Does DISABLE_WP_CRON stop scheduled posts from publishing?
It stops visits from triggering the schedule, so without a server cron job scheduled posts miss their time. With the job in place they publish on the first run after the scheduled minute.
Can I use wget instead of curl?
Yes. wget -q -O /dev/null followed by the same wp-cron.php address does the same job. What matters is that something requests the endpoint on a fixed interval.
Hannah Voss, Editor. Checks every guide against a working WordPress install and the networks' current documentation. Last reviewed September 2026.
Related reading
- Share count not updating or not accurate: a fix listShare counts stuck at zero or wrong? Work through tokens, caches, cron, URL variants and rate limits in order, and why you should never add fake shares.6 min read
- Plugin troubleshooting: what to try firstTroubleshoot a WordPress plugin problem in a safe order: caches, conflicts, debug logging, recovery mode, and disabling a plugin when the admin is down.6 min read
- Fixing the get_currentuserinfo() is deprecated noticeWhat the get_currentuserinfo() is deprecated notice means, how to find the plugin or theme calling it, and the one-line fix using wp_get_current_user().6 min read