WordPress7 min readPublished: 20 Nov 2024Updated: 29 Jul 2026

WordPress Cron: Fix Missed Tasks and WooCommerce

Why WP-Cron misses scheduled tasks, how it breaks WooCommerce emails and stock sync, and how to move to a server cron job that runs on time every time.

G7Cloud Engineering
Platform team
Share:
Abstract illustration representing wordpress cron: fix missed tasks and woocommerce.
  • WP-Cron is not a real scheduler. It only fires when someone visits the site, so a quiet site runs nothing.
  • Full-page caching makes it worse: cached visits never reach PHP, so nothing triggers the queue.
  • The fix is two lines: disable WP-Cron in wp-config.php and add a server cron job calling wp-cron.php every five minutes.
  • On WooCommerce, a stalled queue means unsent order emails, stock that never releases, and subscriptions that do not renew.
  • Check the queue with wp cron event list --due-now. Anything overdue by hours confirms the diagnosis immediately.

Why does WordPress miss scheduled tasks?

Because WP-Cron is not a scheduler. It is a list of jobs that WordPress checks on page load, and it only runs when someone visits the site. No visitors means no checks, and no checks means nothing runs. A task scheduled for 3am on a quiet site may not fire until the first visitor arrives hours later.

WP-CronServer cron
Triggered byA page loadThe operating system clock
Runs on a site with no trafficNoYes
Runs when pages are cachedNoYes
AccuracyWhenever someone happens to visitTo the minute
Cost per runDelays the visitor who triggered itA separate background process

Every row is a reason to move to server cron. There is no case where WP-Cron is the better option on a production site.

Caching turns a small problem into a total one

Once full-page caching is in front of your site, most visits are served from the cache and never reach PHP at all. WP-Cron therefore never gets called. Sites often see scheduled tasks stop the same week caching was switched on, and the two are rarely connected at the time.

How do I check whether WP-Cron is working?

WP-CLI answers this in one command. Anything sitting in --due-now that should have run hours ago confirms the queue is stalled rather than merely busy.

Inspecting the queue
cd /var/www/example.com

# Everything scheduled, with next run times
wp cron event list

# Only what is overdue right now
wp cron event list --due-now

# Is WP-Cron even reachable?
wp cron test

# Run the whole queue by hand and see what happens
wp cron event run --due-now

# Registered schedules (hourly, twicedaily, daily, plus plugin ones)
wp cron schedule list
wp cron test checks that the site can call its own wp-cron.php, which fails on servers that cannot resolve their own hostname.
Without WP-CLI
# Does the endpoint respond at all?
curl -sI https://example.com/wp-cron.php?doing_wp_cron

# Is it disabled in wp-config.php?
grep -i 'DISABLE_WP_CRON\|ALTERNATE_WP_CRON' wp-config.php

# Read the queue straight from the database
wp db query "SELECT option_value FROM wp_options WHERE option_name='cron'" \
  | head -c 2000
A 200 or 302 from wp-cron.php is normal. A 403 usually means a security plugin or firewall rule is blocking it.
SymptomAlmost certainly
Scheduled posts stay in "Missed schedule"The queue is not running at all
Order emails arrive hours late, or in burstsOnly running when a visitor happens to arrive
Backup plugin skipped last nightNo overnight traffic to trigger it
Stock stays reserved after an abandoned checkoutWooCommerce cleanup tasks are not firing
Everything runs, but the site feels slow at randomWP-Cron is running inline and delaying visitors

The last row is the other failure mode: WP-Cron working, but making a visitor wait for it.

How do I replace WP-Cron with a server cron job?

Two steps. Disable the traffic-triggered behaviour in wp-config.php, then have the operating system call the same endpoint on a fixed schedule. Five minutes is the right interval for almost every site.

Step 1: wp-config.php
// Add above the line that says "That's all, stop editing!"
define('DISABLE_WP_CRON', true);
This stops page loads triggering the queue. Nothing will run until you complete step 2, so do both together.
Step 2: the cron job
# Edit the crontab for the user that owns the site
sudo crontab -u www-data -e

# Preferred: WP-CLI, no HTTP request involved
*/5 * * * * cd /var/www/example.com && /usr/local/bin/wp cron event run --due-now --quiet

# Alternative: call the endpoint over HTTP
*/5 * * * * curl -sS -o /dev/null https://example.com/wp-cron.php?doing_wp_cron

# Confirm it is installed
sudo crontab -u www-data -l
The WP-CLI form is better: it skips the web server entirely, so caching, firewalls and TLS cannot interfere with it.

Use the site's own user, not root

Running WP-CLI as root creates files owned by root inside your web root, which the web server then cannot write to. WP-CLI will warn you and refuse by default. Always use crontab -u www-data -e, or whichever user owns the site. See Linux file permissions for web servers.

Verify it is actually running
# Is cron executing the job?
grep CRON /var/log/syslog | tail -20            # Debian / Ubuntu
sudo journalctl -u crond --since '1 hour ago'  # RHEL family

# Should be empty a few minutes after each run
wp cron event list --due-now

# Log the output so you can see failures
*/5 * * * * cd /var/www/example.com && /usr/local/bin/wp cron event run --due-now \
  >> /var/log/wp-cron.log 2>&1
Log it. A cron job that fails silently looks identical to one that is working, until you notice a week of missing emails.

What breaks on WooCommerce when cron stalls?

More than most people realise. WooCommerce runs a great deal through the scheduler, and it also runs Action Scheduler on top of it, which handles the bulk of the background work. When the queue stalls, the shop keeps taking orders while quietly failing to complete them.

TaskWhat customers see when it stalls
Order confirmation emailsNo confirmation, followed by a support ticket
Stock release after a failed paymentProducts showing out of stock that are not
Subscription renewalsRenewals never charged, revenue quietly lost
Abandoned cart cleanupThe database grows and admin pages slow down
Product feed and stock syncMarketplace listings drift out of date
Scheduled sale pricesA sale that starts or ends on the wrong day

Rows one and three are the expensive ones, and both fail silently.

Checking Action Scheduler
# Overall queue health
wp action-scheduler status

# Anything stuck as pending long past its date
wp action-scheduler list --status=pending --per_page=20

# Run the queue by hand
wp action-scheduler run

# Clear out completed and failed records: this table gets very large
wp action-scheduler clean --batch-size=1000

# How big has it grown?
wp db query "SELECT COUNT(*) AS actions FROM wp_actionscheduler_actions"
A wp_actionscheduler_actions table with millions of rows is a common cause of a slow WooCommerce admin.

Action Scheduler is visible in the admin

WooCommerce, Status, Scheduled Actions shows the queue with statuses and timestamps, without any command line. If Pending has thousands of entries with dates in the past, cron has not been running and you have your answer.

If the queue is running but slowly, the constraint is usually database or CPU rather than the schedule. Troubleshooting high CPU and memory on WordPress covers finding out which, and safely trimming a large WooCommerce database covers the table growth that causes it.

How often should the cron job run, and what if it overlaps?

Every five minutes suits almost every site. Every minute is worth it for a busy shop where order emails should be near-instant. Anything less frequent than fifteen minutes starts to feel broken to customers waiting on a confirmation.

IntervalSuitsTrade-off
*/1 * * * *Busy shops, near-instant emailsMore background load, rarely a problem
*/5 * * * *Almost every siteThe sensible default
*/15 * * * *Low-traffic brochure sitesCustomers may notice the delay on a form
0 * * * *Nothing time-sensitive at allToo slow for anything transactional

Start at five minutes. Move to one only if you can point at something that needs it.

Preventing overlapping runs
# flock stops a second run starting while the first is still going
*/5 * * * * /usr/bin/flock -n /tmp/wpcron-example.lock \
  /bin/sh -c 'cd /var/www/example.com && /usr/local/bin/wp cron event run --due-now --quiet'
-n means fail immediately rather than queue. Without this, a long-running job on a one-minute schedule can pile up and exhaust your PHP workers.

Overlapping cron runs can take a site down

If one run takes eight minutes and the job fires every five, you accumulate concurrent PHP processes until the pool is exhausted and the site returns 502. Always use flock on anything scheduled more often than it reliably completes.

This is one of the things a managed platform should handle for you. On G7Cloud, WordPress scheduled tasks run from a system cron on the site's own container rather than depending on visitor traffic, so a quiet site and a heavily cached site both keep their queues moving. See how our WordPress hosting works.

Frequently asked questions

Why are my WordPress scheduled posts missing their schedule?

Because WP-Cron only fires when someone loads a page. A post scheduled for 3am on a site with no overnight visitors will not publish until the first visit afterwards. Full-page caching makes it worse, since cached visits never reach PHP. Replace WP-Cron with a server cron job.

Should I disable WP-Cron?

Yes, on any production site, but only as half of the change. Set define('DISABLE_WP_CRON', true); in wp-config.php and add a server cron job calling the queue every five minutes. Disabling it without adding the cron job stops every scheduled task on the site.

What is the difference between WP-Cron and Action Scheduler?

WP-Cron is WordPress's own scheduler, triggered by page loads. Action Scheduler is a queue library that WooCommerce and many plugins use for background work, and it is itself started by WP-Cron. If WP-Cron stalls, Action Scheduler stalls with it.

How often should the WordPress cron job run?

Every five minutes for most sites. Every minute for a busy shop where order confirmations should arrive immediately. Use flock at that frequency so a slow run cannot overlap with the next one and exhaust your PHP workers.

Is WP-CLI or curl better for the cron job?

WP-CLI. It runs PHP directly with no HTTP request, so page caching, firewall rules, bot protection and TLS problems cannot interfere. The curl form is a reasonable fallback on hosting that does not offer WP-CLI or shell access.

Why do my WooCommerce order emails arrive late?

Usually a stalled scheduler. WooCommerce queues most emails rather than sending them during checkout, so if nothing is processing the queue they sit there until a visitor triggers it. Check WooCommerce, Status, Scheduled Actions for pending items with dates in the past.

Put this into practice on G7Cloud

Every site runs in its own dedicated container behind ScaleShield, with daily backups that are restore-tested every night. Start on the free plan, no card needed.

About G7Cloud Engineering

Platform team

Articles written by the engineers who build and run G7Cloud: UK managed hosting and the AI Website Builder. We write about what we operate every day: containers, backups, databases, and the small-business websites that run on them.

More about G7Cloud →