WP-Cron is how WordPress runs scheduled work: publishing a post at 09:00, sending a newsletter, taking a backup. It has one big catch: it only runs when someone visits your site. On a quiet site, or behind a cache, tasks run late or not at all, and WordPress does not tell you.
The fix is old and simple: let a real scheduler start those tasks instead.
In short
- Have a real scheduler call
https://yoursite.com/wp-cron.phpevery 5 minutes. - Add
define( 'DISABLE_WP_CRON', true );towp-config.php. - Check that tasks run on time and nothing is overdue.
What WP-Cron actually does
On every page load, WordPress checks a list of scheduled tasks. If one is due, it sends a request to wp-cron.php on its own site in the background, and that request runs the task. So WP-Cron is not a clock, it is a check that rides along on visitor traffic. That fails in predictable ways:
- No visitors, no tasks. A post due at 09:00 goes out when the first visitor arrives.
- Caching hides the visits. With full page caching or a CDN, most visits never reach PHP.
- The background request can fail. Some hosts, firewalls and password protection block it, and then nothing runs at all.
Signs you have this problem: posts saying Missed schedule, pending WooCommerce scheduled actions piling up, late emails, or Site Health warning that a scheduled event is late.
Step 1: Set up a real trigger
Do this first, before touching wp-config.php, so there is never a gap.
Option A, a crontab on your own server:
# With WP-CLI: run every task that is due, every 5 minutes
*/5 * * * * cd /var/www/yoursite && wp cron event run --due-now --quiet
# Without WP-CLI: call wp-cron.php over HTTP
*/5 * * * * curl -fsS --max-time 60 "https://yoursite.com/wp-cron.php?doing_wp_cron" > /dev/null 2>&1
Option B, your hosting control panel: cPanel and Plesk have a cron or scheduled tasks screen. Use:
wget -q -O - "https://yoursite.com/wp-cron.php?doing_wp_cron" > /dev/null 2>&1
Option C, an external cron service: the easiest choice on managed hosting or for many sites, because it works on any host and a good one tells you when a call fails. Point it at https://yoursite.com/wp-cron.php?doing_wp_cron every 5 minutes. (I build CronEngine, which does exactly this, with a free plan.)
Step 2: Switch off the built-in WP-Cron
Add this to wp-config.php, above /* That's all, stop editing! */:
// Scheduled tasks are now started by a real cron job.
define( 'DISABLE_WP_CRON', true );
Nothing is deleted. Every task stays scheduled, and wp-cron.php still runs them whenever it is called.
Step 3: Check that it works
- In the free WP Crontrol plugin, no event should be more than one interval overdue.
- Schedule a test post a few minutes ahead and see it go live without visiting the site.
- A 401 or 403 from
wp-cron.phpusually means a firewall or password protection blocks the call; a 500 means a plugin's task hit an error.
How often?
Calling wp-cron.php when nothing is due costs almost nothing. Every 15 minutes is fine for a blog, every 5 minutes for most sites, every 1 to 5 minutes for WooCommerce.
The full guide, with multisite, Cloudflare and managed hosting notes, is on cronengine.com.
Top comments (0)