Skip to content
WordPress6 min read

WP-Cron and Background Jobs Done Properly

WP-Cron is not cron, and treating it as if it were causes missed emails, stuck queues and slow requests. How to run WordPress background work reliably.

Scheduled posts that never publish, order emails that arrive in clumps at nine in the morning, backups that silently stopped weeks ago: most of these mysteries share one cause. WP-Cron is not a scheduler in the operating-system sense. It is a queue that only runs when someone visits the site, and the moment you understand that, both its failure modes and the fix become obvious. The proper setup takes about ten minutes, which makes the years many sites spend without it all the stranger.

How WP-Cron actually works

On every page load, WordPress checks whether any scheduled events are due, and if so fires a loopback request to itself to process them. Two consequences follow. On a quiet site, nothing runs between visits, so a task scheduled for 3am actually runs when the first visitor arrives. On a busy site, real visitors pay the cost of triggering the check, and heavily cached sites may serve thousands of pages without ever reaching PHP, which starves the queue in a different way. It is a clever default for shared hosting with no cron access, and the wrong tool for anything you rely on.

Switch to real cron

The fix is two small changes: tell WordPress to stop piggybacking on traffic, and have the system scheduler drive the queue instead. Every due event now runs within five minutes of its scheduled time, regardless of traffic, and visitor requests never carry the work.

bash
# wp-config.php
# define( 'DISABLE_WP_CRON', true );

# System crontab, every five minutes
*/5 * * * * cd /var/www/site && wp cron event run \
  --due-now >/dev/null 2>&1

Using WP-CLI rather than hitting wp-cron.php over HTTP avoids web-server timeouts and gives jobs a proper PHP process with CLI limits. On managed hosting, look for a setting that does exactly this; most good hosts provide one.

Scheduling your own events well

Registering a recurring task is straightforward, but two habits keep it robust. Always guard wp_schedule_event with a wp_next_scheduled check, otherwise every activation stacks another copy of the event and your task starts running in duplicate. And keep the callback idempotent, so that a job which runs twice, or dies halfway and reruns, does no damage. WP-Cron guarantees at-least-once behaviour on a good day, not exactly-once, and code that pretends otherwise eventually sends a customer three invoices.

Custom intervals are registered through the cron_schedules filter and deserve the same defensiveness: check the name is free before adding it, and keep schedules as coarse as the job allows. A task that runs every minute needs to justify itself, because it competes with everything else on the server for the same PHP workers.

Bigger workloads: batches and Action Scheduler

A cron callback that processes ten thousand records in one run will hit a memory or time limit eventually, and when it dies mid-batch it leaves no record of where it got to. For serious background work we reach for Action Scheduler, the queue library that ships inside WooCommerce and is available standalone: individually persisted actions, automatic retries with a claim system, and an admin screen showing exactly what ran, failed or is pending. Enqueue one action per item rather than one action for the whole batch, and the system becomes self-healing.

Monitor it like the infrastructure it is

Whatever runs your jobs, watch it. wp cron event list shows the queue and, crucially, events whose next run is in the past, which is the signature of a stalled queue. WP Crontrol offers the same visibility in the admin for teams who live there. For anything business-critical, add a heartbeat: a tiny scheduled task that pings a monitoring service, so silence pages a human instead of being discovered a month later. For substantial jobs, log start, finish and duration too; a task that used to take a minute and now takes twenty is a warning you want to receive early.

Background reliability is invisible when it works, which is exactly why it is worth setting up properly once. If your scheduled jobs have become a source of superstition rather than confidence, STRCLI can help you put them on solid ground.

#wp-cron#background-jobs#performance#reliability
All articles

Start your project

Have an idea? Let's ship it together.

Tell us what you're building — we'll reply within one business day with an honest take and a clear next step.