Guide WordPress

How to replace WP-Cron with a real cron job

WP-Cron piggybacks on visitor traffic rather than running on a real schedule. Here is how to replace it with one that does.

Updated 7 min read Intermediate

WordPress does not have real scheduled tasks running in the background the way the name "WP-Cron" suggests. Instead, every time a page loads, WordPress checks whether any scheduled task is currently due and, if so, runs it right then, as part of handling that visitor's request. It is a clever way to get scheduling without needing server-level access, and it works reasonably well on a busy site. On a quiet one, it means scheduled tasks only run whenever the next visitor happens to arrive — which could be minutes after they were due, or hours.

Why this becomes a problem

  • Tasks run late on low-traffic sites. A backup scheduled for 3am does not run at 3am if nobody visits until 8am.
  • Tasks add load to every page view on busy sites. WordPress checks for due tasks on every single request, which is unnecessary overhead multiplied across every visitor, most of whom will find nothing due.
  • A burst of simultaneous visitors can trigger a task more than once. WP-Cron has some protection against this, but it is not as reliable as a single task genuinely running once, on schedule, independent of traffic.

Replacing it with a real, server-level cron job fixes all three: the task runs exactly when scheduled regardless of whether anyone is visiting, and ordinary page loads stop carrying the overhead of checking for due tasks.

Step 1: stop WordPress's own pseudo-cron

Add this line to wp-config.php, above the line that reads /* That's all, stop editing! */:

define( 'DISABLE_WP_CRON', true );

This stops WordPress from checking for due tasks on every page load. It does not disable scheduling itself — tasks are still registered and due times still tracked — it just stops WordPress from being the thing that triggers them. Something else now has to do that job, which is the real cron job you are about to set up.

Do not add this line without setting up the replacement

If you add DISABLE_WP_CRON and stop there, scheduled tasks stop running altogether — nothing publishes on schedule, no scheduled cleanup jobs fire, and nothing tells you this has happened, because there is no error, just silence. Set up the real cron job in the same sitting.

Step 2: create a real cron job

In your hosting control panel's cron job section, create a new scheduled task that requests wp-cron.php directly, on a fixed interval. Every 15 minutes is a sensible default for most sites — frequent enough that scheduled tasks run close to on time, infrequent enough not to add meaningful load.

wget -q -O /dev/null "https://yourdomain.com/wp-cron.php?doing_wp_cron"

If your control panel's cron interface asks for a curl command instead, the equivalent is:

curl -s "https://yourdomain.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1

Either one simply visits the URL on schedule, the same way a real visitor loading any page would, which is enough to trigger WordPress's own check for due tasks — the only difference is that it now happens on a fixed timer instead of depending on whoever happens to show up.

Step 3: use WP-CLI instead, if you have it

Where SSH access is available, WP-CLI can trigger due events directly without a web request at all, which is marginally more efficient and does not depend on the site being publicly reachable:

wp cron event run --due-now

Point your control panel's cron job at this command instead of a URL if you have WP-CLI set up. See using WP-CLI on your hosting if you have not used it before.

Step 4: confirm it is actually working

Do not assume it is working simply because no error appeared. Check that:

  • A scheduled post actually publishes at its scheduled time rather than late.
  • Any plugin with its own scheduled tasks — backups, cleanup jobs, digest emails — still fires as expected over the following day or two.
  • Your control panel's cron job log, if it has one, shows the task running successfully on its interval rather than failing silently.

If scheduled tasks stop firing after this change, the most common cause is a typo in the URL or command, or the cron job pointing at the wrong site if the account hosts more than one. Recheck the exact command against your domain before assuming something deeper is wrong.

See setting up a cron job for a general walkthrough of your control panel's scheduling interface if this is the first one you have created.

Frequently asked questions

Do I need to do this on every WordPress site?

No. A low-traffic site with light scheduled tasks — the default WordPress ones and not much else — usually runs fine on the default WP-Cron behaviour. It becomes worth doing once a site has real traffic and several plugins each registering their own scheduled jobs, or once you notice scheduled tasks running late.

What happens to scheduled tasks between visits if I do nothing?

They simply wait. WP-Cron checks whether anything is due every time a page loads, so on a quiet site a task scheduled for 2am might not actually run until the first visitor arrives at 9am. Nothing is lost, but nothing runs on time either.

Related reading