Emergency WordPress Hack Cleanup?
sales@inceptusdigital.com |
← Back to Insights

WP-Cron Not Working? Fix Missed Scheduled Posts and Stuck WooCommerce Actions

By Sameer Hussain WordPress
WP-Cron Not Working? Fix Missed Scheduled Posts and Stuck WooCommerce Actions

Scheduled posts show "Missed schedule". WooCommerce emails go out hours late. Subscription renewals don't run, backups don't happen, and WooCommerce → Status → Scheduled Actions shows a growing pile of "Past-due" actions. All of these point to one thing: WP-Cron isn't running. Here's why that happens and how to set it up so it runs reliably.

How WP-Cron actually works

WP-Cron isn't a real cron job. WordPress has no background process. Instead, on each page load, WordPress checks whether any scheduled task is due. If one is, it sends a request to yoursite.com/wp-cron.php (called a loopback request) to run it in the background.

That design has two weak points:

  1. No visitors means no cron. On a low-traffic site, or a site whose pages are all served from cache, WordPress may not run for hours, and nothing scheduled happens.
  2. The loopback request can fail. If the server can't reach itself over HTTP, cron never fires even on busy sites.

Step 1: Find out what's wrong

Check Site Health

Go to Tools → Site Health. Two results matter here:

  • "A scheduled event has failed" or "A scheduled event is late": cron is running badly or not at all.
  • "Your site could not complete a loopback request": the server can't call itself, so wp-cron.php never runs.

Check with WP-CLI

# Can WordPress spawn cron?
wp cron test

# What's scheduled, and is anything overdue?
wp cron event list --fields=hook,next_run_relative,recurrence

# Is cron disabled in wp-config.php?
wp config get DISABLE_WP_CRON

Events with a next_run_relative in the past ("2 hours ago") confirm cron isn't firing. If DISABLE_WP_CRON returns true, someone turned WP-Cron off, which is fine only if a real server cron job replaced it. Often, nobody set one up.

Step 2: Fix failed loopback requests

If Site Health reports a failed loopback, the usual causes are:

  • HTTP Basic Auth on a staging or password-protected site blocks the server's request to itself.
  • A firewall or security plugin blocks requests to wp-cron.php, or blocks the server's own IP.
  • Cloudflare or a WAF rule challenges the request. A bot check can't be passed by a server.
  • DNS on the server resolves your domain to the wrong IP (common right after a migration), so the loopback goes to the old server.
  • A plugin with a PHP error breaks every request, including the loopback. Check debug.log.

You can often get cron working anyway by switching to a real server cron job, which avoids the loopback entirely. That's the next step, and it's what I set up on every production site.

Step 3: Replace WP-Cron with a real server cron job

First, stop WordPress from triggering cron on page loads. Add this to wp-config.php, above the "stop editing" line:

define( 'DISABLE_WP_CRON', true );

Then add a cron job on the server that runs scheduled tasks every 5 minutes.

Best option: WP-CLI (if your host has it)

*/5 * * * * cd /home/user/public_html && /usr/local/bin/wp cron event run --due-now --quiet >/dev/null 2>&1

This runs PHP directly with no HTTP request, so there's no firewall, auth or timeout problem. Use the real path to your site and to wp (find it with which wp).

Alternative: call wp-cron.php over HTTP

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

Simple, and it works on almost any host, but the request has to get past your firewall and Cloudflare like any other request.

Adding the job in cPanel

Go to Advanced → Cron Jobs, pick "Once Per Five Minutes" from Common Settings, and paste the command (without the */5 * * * * part, since cPanel fills in the timing). Managed WordPress hosts like Kinsta and WP Engine often run server cron for you already. Check their docs before adding your own.

Step 4: Clear the Action Scheduler backlog (WooCommerce)

WooCommerce, subscriptions plugins, many email plugins and others queue background work in Action Scheduler, which runs on top of WP-Cron. Once cron is fixed, the backlog works through on its own, a batch at a time. For a large backlog, you can process it faster from the command line:

# See what's pending
wp action-scheduler list --status=pending --format=count

# Process the queue now
wp action-scheduler run --batch-size=100

Also look at failed actions under WooCommerce → Status → Scheduled Actions. If the same hook fails thousands of times, the problem isn't cron. That action itself is broken, often a webhook pointing at a URL that no longer exists. Open one of the failed actions to read its log message.

Fixing posts already marked "Missed schedule"

Posts that missed their publish time won't publish on their own afterwards. Once cron works, publish them manually, or list them with:

wp post list --post_status=future --fields=ID,post_title,post_date

Posts with a past post_date in that list missed their schedule. Open each one and click Publish.

Verify it's working

After an hour, run wp cron event list again. Nothing should be more than a few minutes overdue. The WP Crontrol plugin gives you the same view in wp-admin, plus the ability to run individual events manually, which is very handy for testing.

SH

Written by

Sameer Hussain, Senior Shopify & WordPress Engineer

Top Rated on Upwork and the Shopify & WordPress engineer at Inceptus Digital. Short on time, or not comfortable editing code? Send me your URL and the error on Upwork and I'll tell you how I'd fix it before you commit.

Share this article

Need Custom Engineering or Growth Systems?

Our team helps ambitious brands build bespoke software, AI integrations, and high-conversion platforms.

Chat on WhatsApp