Action Scheduler is a job queue inside WordPress. WooCommerce uses it for webhook deliveries, analytics imports and cleanup tasks, WooCommerce Subscriptions for renewals, and many other plugins for their own work. You can see it under WooCommerce › Status › Scheduled Actions, or Tools › Scheduled Actions without WooCommerce. When it gets stuck, nothing is lost, it is just late. The fix is almost always the same: make sure the queue is processed regularly, and find the one plugin whose actions keep failing.
In short
- 1Open Scheduled Actions and check two things: Pending actions with dates in the past, and Failed actions with an error in the log.
- 2Past-due pending actions mean the queue is not being run. Make WP-Cron run on a real schedule, every minute for a shop.
- 3For a big backlog, run the queue with
wp action-scheduler runfrom a server cron job.
How Action Scheduler runs
Action Scheduler does not have a clock of its own. It is started in two ways:
- By WP-Cron, through the
action_scheduler_run_queuehook, at most once a minute. - At the end of admin page loads, when actions are due, through a background request to the site itself.
Each start claims a batch of 25 actions and processes them for up to 30 seconds, one batch at a time. So the queue moves only as often as WP-Cron runs or someone uses the admin. And WP-Cron itself only runs when someone visits the site, as explained in how to replace WP-Cron. A shop with few visitors, full page caching or a broken loopback request ends up with a queue that barely moves.
What the warning means
The admin notice looks like this:
Action Scheduler: 37 past-due actions found; something may be wrong. Read documentation »
It appears when at least one pending action is more than a day past its scheduled time. Some past-due actions are normal, according to Action Scheduler's own documentation. Actions more than a day late are not: something is stopping the queue. The link in the notice opens the list of exactly those actions.
Find out which problem you have
Open Scheduled Actions and look at the status tabs:
| What you see | What it means | Go to |
|---|---|---|
| Many pending actions with dates in the past, few failures | The queue is not being run often enough | Fix 1, 2 and 3 |
| Many failed actions with the same hook | One plugin's task keeps throwing an error | Fix 4 |
| Actions stuck in-progress | A run died halfway, usually a fatal error or a timeout | Fix 4 |
| Hundreds of thousands of complete actions, a slow admin | The table has grown too big | Fix 5 |
Also open Tools › Site Health. A message that a scheduled event is late, or that the site could not complete a loopback request, confirms that WP-Cron itself is the problem.
Fix 1: Make WP-Cron run reliably
This fixes most stuck queues. Let a real scheduler call wp-cron.php on a fixed schedule, and switch off the
check on page loads. For a shop, every minute keeps Action Scheduler moving as fast as it is designed to.
https://yourshop.com/wp-cron.php?doing_wp_cron
// Scheduled tasks are now started by a real cron job.
define( 'DISABLE_WP_CRON', true );
Set up the scheduler before adding that line. A common cause of a stuck queue is
DISABLE_WP_CRON left in wp-config.php after a move, with nothing calling wp-cron.php at all.
The WP-Cron guide covers the crontab, the hosting panel and an external
service step by step.
With CronEngine it is one job for that URL. It works on any host, keeps a history of every call, and emails you when your shop stops answering, which is usually the first sign the queue will pile up again.
Fix 2: Clear the backlog now
With WP-Cron fixed, the backlog clears by itself, 25 actions at a time. To speed that up for a few important ones, hover over a pending action in Scheduled Actions and click Run. That runs it straight away, in your browser request.
For hundreds or thousands of actions, clicking is no option. Use WP-CLI, below, or wait: at one batch a minute, a backlog of a few thousand is gone within a few hours.
Fix 3: Run the queue with WP-CLI
Action Scheduler's documentation calls WP-CLI the best way to process large queues. It runs from the command line, so the web server's time limits do not apply, and it can keep going until the queue is empty.
# Run everything that is due, until the queue is empty wp action-scheduler run # Only one plugin's actions, for example subscription renewals wp action-scheduler run --hooks=woocommerce_scheduled_subscription_payment # Run even when another queue runner is already busy wp action-scheduler run --force
On a server where you have SSH and a crontab, run it every minute next to WP-Cron. Actions are claimed before they run, so the two runners do not process the same action twice.
* * * * * cd /var/www/shop && wp action-scheduler run --quiet
Fix 4: Deal with failed actions
Open the Failed tab and look at the hook names and the log column. The hook tells you which plugin scheduled the action, and the log usually holds the error message. Many failures with the same hook point to one plugin: update it, check its settings, or contact its developer with that message.
Actions that sit in-progress were started and never finished, mostly because PHP hit a fatal error or a time limit halfway. Action Scheduler handles these itself: a claimed action that never started is released after 5 minutes, and an action still running after 5 minutes is marked failed. The PHP error log from that moment shows what went wrong.
Fix 5: Keep the table small
Completed and canceled actions are kept for 31 days, then deleted in batches. On a busy shop that can still be millions of rows, which makes the Scheduled Actions screen and the queue itself slower. A shorter period is safe for most shops:
// Keep finished actions for 7 days instead of 31.
add_filter( 'action_scheduler_retention_period', function () {
return WEEK_IN_SECONDS;
} );
The cleanup runs each time the queue runs. If the queue was stuck, the cleanup was too, so the table shrinks once Fix 1 is in place.
Tuning, carefully
Three filters change how much each run does. The defaults are deliberately safe for shared hosting:
| Filter | Default |
|---|---|
action_scheduler_queue_runner_batch_size | 25 actions per batch |
action_scheduler_queue_runner_time_limit | 30 seconds per run |
action_scheduler_queue_runner_concurrent_batches | 1 batch at a time |
Raise them only when the queue runs regularly and still cannot keep up, and one step at a time. Action Scheduler's own documentation warns that more concurrent batches can substantially increase server load and take a site down. WP-CLI is the safer way to more throughput.
Questions
Is it normal to have some past-due actions?
Yes. Action Scheduler's own documentation says that because of how WP-Cron works, some past-due actions are normal. Several that are more than a day old point to a real problem, and that is exactly when the warning appears.
Can I just hide the "past-due actions found" warning?
There are filters that do, but the actions are still not running: renewals, emails and stock updates stay late. Fix why the queue is not processed, and the warning goes away by itself.
Is it safe to delete the pending actions?
Usually not. A pending action is work a plugin still expects to happen, such as a subscription renewal or a webhook delivery. Run them instead. Only delete old completed and canceled actions, and let the built-in cleanup do it.
I set DISABLE_WP_CRON and now nothing runs. Why?
That constant only stops page loads from starting WP-Cron. Something else has to call wp-cron.php, or run the queue with WP-CLI, on a schedule. Without that, WP-Cron and Action Scheduler both stop.
How often should wp-cron.php be called for a WooCommerce shop?
Every minute is ideal for a busy shop, because Action Scheduler starts at most one batch per WP-Cron run and runs at most once a minute. Every 5 minutes is fine for a small shop. With a large queue, add WP-CLI on the server as well.
What do the hook names in the list tell me?
Which plugin scheduled the action. Hooks starting with woocommerce_, wc_ or wc-admin_ belong to WooCommerce, and most other plugins use their own prefix. That tells you which plugin to look at, or update, when its actions fail.
Spotted a mistake, or something that behaves differently for you? Tell us and we will update the guide.