DEV Community

Cover image for How to replace WP-Cron with a real cron job
Adriaan De Kaey
Adriaan De Kaey

Posted on Originally published at cronengine.com

How to replace WP-Cron with a real cron job

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

  1. Have a real scheduler call https://yoursite.com/wp-cron.php every 5 minutes.
  2. Add define( 'DISABLE_WP_CRON', true ); to wp-config.php.
  3. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 );
Enter fullscreen mode Exit fullscreen mode

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.php usually 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)