How WP-Cron works in WordPress

How WP-Cron works in WordPress (and why it sometimes fails)

WP-Cron is WordPress’ built-in scheduling system. It quietly handles a lot of “automatic” work that users assume just happens on its own, like publishing scheduled posts, checking for updates, or running recurring plugin tasks in the background.

  • Publishing scheduled posts
  • Checking for plugin and theme updates
  • Sending scheduled emails (newsletters, digests, notifications)
  • Running backup and maintenance routines
  • Cleaning up temporary data and expired items
  • Running security tasks like scans or housekeeping jobs

The important detail is this: WP-Cron is not a real server cron daemon. It’s a “pseudo-cron” system that relies on website traffic to trigger the check. That design makes WordPress portable (it works on almost any hosting), but it also explains why scheduled tasks can run late or cause performance issues.

What is WP-Cron?

On a typical Linux server, a real cron job runs at fixed times or intervals, whether anyone visits the website or not. That’s why server cron is predictable: it runs because the server says so.

WP-Cron works differently. WordPress checks for due tasks during normal page loads and then triggers cron processing if something is scheduled to run. In practical terms, it looks like this:

  • A visitor (or bot) requests any page on your site
  • WordPress loads and checks the schedule (stored in the database)
  • If events are due, WordPress triggers cron processing

No traffic means no trigger. That’s the reason low-traffic sites sometimes miss schedules. And it’s also why high-traffic sites can end up triggering cron too often unless you control it.

How WP-Cron runs tasks behind the scenes

Your scheduled events are stored in the WordPress database. When WordPress detects that an event is due, it calls wp-cron.php to process the queue.

A key reason WordPress calls wp-cron.php via an HTTP request is user experience: some cron tasks can take time. If WordPress tried to execute everything inside the same page request, visitors could end up waiting for a slow page load. Instead, WordPress attempts to “spawn” cron as a background request so the visitor gets their page while cron work happens separately.

Cron processing continues until all due jobs are finished or until the server execution limits (timeouts, worker limits, etc.) cut it off. That’s why hosting quality and server configuration can directly affect cron reliability.

Which functions are used to schedule jobs?

Developers schedule tasks using WordPress’ Cron API. The most common functions are:

  • wp_schedule_event() for recurring events
  • wp_schedule_single_event() for one-time events
  • wp_next_scheduled() to check if something is already scheduled
  • wp_clear_scheduled_hook() to remove scheduled events

WordPress includes some default recurrence intervals such as hourly, twicedaily, daily, and weekly. Plugins and custom code can also add additional intervals using the cron_schedules filter.

Why WP-Cron can be unreliable

WP-Cron is a clever compromise, but it’s still a compromise. The same design that makes it easy to run on any hosting also creates the most common problems.

1. Low traffic websites: scheduled tasks run late

If your site doesn’t get visitors around the time a task is due, it may not run until the next visit happens. That can lead to real-world annoyances like scheduled posts publishing late, queued emails going out late, or maintenance jobs not running on time.

  • Scheduled posts publish “whenever someone visits next”
  • Backups and cleanups may be delayed
  • Security scans can be postponed, creating blind spots

2. High traffic websites: too many cron spawns

On busy sites, WP-Cron checks can happen frequently. WordPress does use a lock to help prevent cron from spawning repeatedly at the same time (it stores a lock in the doing_cron transient), but high concurrency can still create churn.

The typical symptoms look like this:

  • Higher CPU usage than expected
  • Multiple PHP workers tied up doing background work
  • Performance spikes even if front-end traffic looks “normal”

Some hosts also rate-limit outgoing loopback requests (your site calling itself), and that can break cron spawning in subtle ways.

3. Long-running tasks: timeouts and partial completion

Cron jobs aren’t all equal. Some tasks are quick (like checking an option), while others are heavy (like scanning files, generating reports, or importing large datasets). If a cron callback takes too long, it can hit PHP time limits, memory limits, or worker limits. The result can be a job that never finishes cleanly, or jobs that repeatedly restart and create load.

How to tell if WP-Cron is working

A quick basic test is to visit:

https://yourdomain.com/wp-cron.php

You will usually see a blank page, which simply means the endpoint is reachable. It does not guarantee everything is perfect, but it confirms the file can be executed.

If you want a clearer view of what’s scheduled and what is running, a plugin like WP Crontrol can show you scheduled events, next run times, and which hooks are queued. This is often the fastest way to discover a plugin that is scheduling too aggressively or failing repeatedly.

The recommended approach: disable WP-Cron and use a real server cron

For many production websites, the most stable solution is:

  1. Disable the automatic spawn-on-page-load behavior
  2. Trigger cron using a real server cron job on a fixed schedule

This gives you predictable timing and stops cron checks from happening on every page load.

Step 1: Disable WP-Cron spawning

Edit your wp-config.php file and add this line just above the “That’s all, stop editing” comment:

define( 'DISABLE_WP_CRON', true );

Important note: this does not “turn off cron forever”. It only stops WordPress from spawning cron automatically on page loads. Cron will still run when you call wp-cron.php directly (which is exactly what we’ll do in step 2).

Step 2: Add a server cron job to call wp-cron.php

In your hosting control panel (or via SSH crontab), create a cron job that runs every 5 minutes.

Using wget:

wget -q -O - https://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Using curl:

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

This approach makes cron independent of traffic. Your tasks run when the server says they should run, not when someone happens to visit.

When should you switch to real cron?

If your website is anything more than a hobby blog, switching is usually worth it. It’s especially recommended when timing matters or when background jobs are part of your business.

  • WooCommerce stores (orders, subscriptions, emails, stock tasks)
  • Membership sites and course platforms
  • Sites relying on scheduled emails or automations
  • Sites running backups, security scans, or monitoring
  • High-traffic sites where cron checks add load

WP-Cron and security: why reliability matters

Many security and maintenance features rely on scheduled jobs. If cron is unreliable, you can end up with tasks that “look enabled” in the UI but simply don’t execute consistently.

That can mean:

  • Scans run late (or not at all)
  • Cleanup tasks don’t happen, leaving junk and logs to grow
  • Scheduled checks fail silently, reducing visibility

If you are running a security plugin that depends on scheduled scans or routine background checks, a real server cron is the safer setup.

WP-Cron is a practical scheduling system built for maximum compatibility, but it has one big weakness: it depends on traffic to trigger.

If your site has low traffic, schedules can be late. If your site has high traffic, cron can be triggered too often and create load.

For most production sites, the best setup is to disable WP-Cron spawning and run cron from the server on a fixed schedule. It’s predictable, reliable, and usually improves performance at the same time.

Written by

Get AI-Powered Security Summary

Let AI analyze this WordPress security article and provide actionable insights from WP Security Ninja experts.

Trusted WordPress Security Expert

Was this helpful?

Next Article

Re-install WordPress