NextWoo
Background jobs

WooCommerce Action Scheduler: why actions go past due and how to clear them

The job queue behind order analytics, webhooks and subscription renewals. It runs only when something wakes it, and on a quiet store, nothing does.

Past-due actions in the WooCommerce Action Scheduler mean the queue is not being started often enough, or a job inside it keeps dying before it finishes. The runner is woken by WP-Cron, which fires only when someone loads a page, and by a loopback request sent while someone is working in wp-admin. Each run then stops at about 30 seconds or 90% of PHP memory. A store with little overnight traffic, or a host that blocks loopback requests, falls behind. The fix is a server cron that runs the queue every minute, then a look at the hook filling it. Start under WooCommerce → Status → Scheduled Actions, on the Past-due view.

01

A job queue with four tables of its own

Action Scheduler is a library that WooCommerce bundles, as do extensions such as Subscriptions and Memberships. WooCommerce 11.2.1 ships version 4.1.0; the standalone plugin on wordpress.org reached 4.2.0 on 16 September 2026. When several plugins carry a copy, the highest version runs, and `wp action-scheduler source` shows whose copy that is. Unlike WP-Cron, which keeps every event in one `cron` option, each job here is a database row: `wp_actionscheduler_actions` holds the hook, arguments, status and due time, `wp_actionscheduler_logs` the history, and `wp_actionscheduler_groups` and `wp_actionscheduler_claims` the grouping and which runner took a batch. On the default Analytics setting each new order schedules `wc-admin_import_orders`, webhooks run as `woocommerce_deliver_webhook_async`, and HPOS sync queues `wc_run_batch_process`.

02

What wakes the queue, and how long each run lasts

Two triggers start a run. One is the `action_scheduler_run_queue` event, registered with WP-Cron every 60 seconds. WP-Cron is not a clock, though: WordPress checks for due events during a page load and only then fires a non-blocking request at its own `wp-cron.php`. No visitors, no run. The other is the async runner, which at the end of a wp-admin request, at most once a minute, posts to `admin-ajax.php` and re-dispatches itself after a 5-second pause while due actions remain. Both are loopback requests: the server calling itself over HTTP. A run claims actions in batches of 25 and stops at 90% of the memory limit or when three more actions would cross 30 seconds.

03

Why actions end up past due

A few actions minutes late is normal; the Action Scheduler FAQ says so. Its admin notice, "past-due actions found; something may be wrong", appears only once a pending action is more than a day overdue. Site Health often speaks first, with "The scheduled event, action_scheduler_run_queue, failed to run." It raises that at 5 minutes overdue, or an hour when `DISABLE_WP_CRON` is set, and because this event recurs every minute it is usually the one named. Beyond that, four causes cover nearly every case.

  • No traffic, so no WP-Cron: a store with no visitors at 3 a.m. runs nothing at 3 a.m., and `DISABLE_WP_CRON` left behind after a host move with no server cron stops the trigger for good.
  • Blocked loopback requests: basic auth on staging, a firewall rule or bot challenge in front of `wp-cron.php` and `admin-ajax.php`, or DNS that keeps the server from reaching its own domain breaks both triggers, which Site Health reports as "Your site could not complete a loopback request".
  • Actions that never finish: one still in-progress after 300 seconds, ten times the batch limit, is marked failed with a log line pointing at the server, PHP and database error logs. A fatal error inside a callback leaves that trace.
  • Host limits: a host that kills web requests at 30 or 60 seconds ends batches early, and a callback that loads thousands of orders hits the memory ceiling mid-batch.
04

Reading the Scheduled Actions screen and its logs

Open WooCommerce → Status → Scheduled Actions and switch to Past-due. The Log column does the diagnosis. Each action records "action created", then "action started via WP Cron", "via Async Request" or "via WP CLI", then complete or failed with the error message. No recent row saying via WP Cron means WP-Cron is not firing. One hook failing with the same message again and again means the queue is fine and that plugin is broken. `wp action-scheduler status` prints the count and oldest date per status. A read-only query finds the hook behind a backlog, with your table prefix in place of `wp_`: `SELECT hook, COUNT(*) FROM wp_actionscheduler_actions WHERE status = 'pending' GROUP BY hook ORDER BY 2 DESC LIMIT 10`.

05

A server cron is the fix that lasts

Add `define( 'DISABLE_WP_CRON', true );` to wp-config.php and have the server run the queue every minute, matching Action Scheduler's own schedule. A crontab line such as `* * * * * wp --path=/path/to/site cron event run --due-now` runs every due WP-Cron event, the queue trigger included, while `wp action-scheduler run` processes actions directly, 100 per batch by default. WP-CLI runs outside the web server, so the host's request timeout never applies. The Action Scheduler docs list 60 seconds on WP Engine and 120 on Pantheon and SiteGround. Calling `wp-cron.php` with wget from cron is the weaker setup, still a web request bound by those limits; keep it for hosts with a cron panel and no shell. Raising `action_scheduler_queue_runner_concurrent_batches` to push more through the web runner is worse again, and the library's own docs warn it can take a site down. Two caveats. Disable WP-Cron without a working replacement and scheduled posts, update checks and every queued action stop together, while Site Health takes 15 minutes to call the event late and an hour to call it failed. And where staff sit in wp-admin all day, the async runner keeps the queue moving alone, so a broken cron can hide all week and surface as a Sunday backlog.

06

Draining a backlog without breaking renewals

Clear a large backlog in steps: `wp action-scheduler run --batch-size=100 --batches=5` handles at most 500 actions and stops, leaving time to check the failed count. The `--hooks` and `--group` options break ordering: the WP-CLI docs use Subscriptions as the example, where a payment and an expiration due a minute apart can run in the wrong order once split across queues. Leave `--force`, which lifts the one-batch limit, off on shared hosting. Never delete pending actions to make the count drop, since each is a renewal, an email or a webhook that then never runs. Any SQL cleanup starts with a backup and a staging run, and touches only complete or canceled rows.

07

The daily cleanup and the retention filters

Since Action Scheduler 4.0.0, bundled from WooCommerce 11.0, cleanup is a daily task at 3 a.m. site time that deletes in batches of at least 250. Complete and canceled actions go after 31 days (2,678,400 seconds), set by `action_scheduler_retention_period`; failed ones after three months, set by `action_scheduler_retention_period_for_failed`. Before 4.0, failed actions were never purged, so an older store may still hold every failure it ever logged. The docs clear those with `wp action-scheduler clean --status=failed --before='90 days ago' --batch-size=50 --pause=2`. Cutting retention to a day or two is the mistake: it deletes the record you need when a customer asks why a renewal email never came.

08

How much a big actions table really slows the store

Less than its size suggests. Cached storefront pages never read these tables. The cost lands in wp-admin, where the Scheduled Actions screen counts every status, in each runner's claim queries (4.0.0 optimized the claim count for large stores), and in writes: on the default Analytics setting every order inserts a `wc-admin_import_orders` row during checkout. Measure before blaming the table for a slow checkout. If Query Monitor does not show `actionscheduler` queries near the top of a checkout request, purging will not change checkout time. When wp-admin is the slow part, the admin slowdown guide covers the other causes.

09

When one plugin floods the queue

The read-only query above usually answers this in one row. A scenario: a bulk edit of 5,000 products with a product.updated webhook active queues 5,000 deliveries at once. Fix the source first, through the plugin's batch setting or a webhook subscribed to fewer topics. Where the volume is legitimate, the docs describe one WP-CLI runner per busy `--group` plus a catch-all using `--exclude-groups`. Speeding up the runner for a plugin that schedules a job per page view only moves the bottleneck into the database.

10

What the free audit checks in the queue

The free store audit reads the counts by status, the age of the oldest past-due action, how WP-Cron is triggered, and which hooks dominate the pending and failed lists. Watching the cron and the queue afterwards is part of maintenance and support, on the Care Plan from $150 a month; speed work is quoted separately, with prices on pricing.

Frequently asked questions

Still have questions?

Reach out and we'll get back to you within 24 hours.

Contact us
Why is Action Scheduler not running?

Usually nothing wakes it: WP-Cron needs page loads, the async runner needs wp-admin requests, and a blocked loopback stops both. A server cron running WP-CLI every minute fixes that.

Are past-due actions in WooCommerce a problem?

Minutes of delay is normal. Action Scheduler warns only when a pending action is more than a day overdue; then check the cron, loopback requests and the failing hook.

What does "action_scheduler_run_queue failed to run" mean?

Site Health is reporting that the WP-Cron event which starts the queue is over 5 minutes late, or an hour with DISABLE_WP_CRON set. WP-Cron is not firing; the actions may be fine.

Can I delete Action Scheduler logs?

Complete and canceled actions are deleted with their logs after 31 days, failed ones after three months. Sooner, use wp action-scheduler clean; delete by SQL only with a backup and a staging test.

What is the WP-CLI command to run Action Scheduler?

wp action-scheduler run. It processes 100 actions per batch until nothing is due; --batches caps the run and --group limits it to one group.

Related reading
  • Slow WooCommerce admin

    WooCommerce admin slow? Check Analytics imports, orders on posts tables, autoloaded options, Action Scheduler, Heartbeat and plugins that call home.

  • HPOS migration

    WooCommerce HPOS explained: the four order tables, plugin compatibility checks, compatibility mode sync, wp wc hpos commands and a staging-first migration.

  • Maintenance and support

    Maintenance for a live WooCommerce store: tested backups, staged updates with rollback, uptime and checkout monitoring, security response and speed watch.

  • WooCommerce speed optimization

    WooCommerce speed optimization service: a free audit, a week of measured fixes on your current theme, and a frontend rebuild only if the theme is the ceiling.

See how many sales your store is losing

Start with a free speed audit. You'll get your store's real numbers and an honest recommendation — even if it's "you don't need us".

Anything you already suspect — checkout feels slow on phones, the category pages crawl, you were told the theme is the problem. Guesses are useful; we check them.

No sales call — you'll get a written report with your store's numbers.

By requesting an audit you accept our Privacy policy and Terms of service. We may publish an anonymised summary of the findings as an example of our work. We never name your business without your written consent.