WooCommerce and many extensions use Action Scheduler for webhooks, subscriptions, email, cleanup and external synchronisation. A growing Pending queue means work is being created faster than runners complete it, while repeated Failed actions indicate a specific callback cannot succeed.
Do not delete the queue to make the count smaller. Some actions represent payments, refunds or fulfilment that still require reconciliation.
Measure the backlog
Open WooCommerce > Status > Scheduled Actions and record Pending, Failed and In-progress counts plus the oldest scheduled time.
Queue health:
oldest pending age
new actions per minute
completed actions per minute
top failing hook names
average/maximum run time
Inspect arguments only through authorised controls; they can contain order or customer identifiers.
Confirm the runner is invoked
WordPress normally triggers cron from web traffic. Check whether DISABLE_WP_CRON is set and whether a real server cron replaces it.
Use cPanel or Plesk scheduling to call WordPress through the host’s supported PHP/HTTP method at a sensible interval. Ensure the command targets the correct site and PHP version.
Do not run multiple overlapping cron configurations without measuring concurrency.
In WordPress multisite, confirm the scheduler invokes the individual store where actions live. A cron request reaching only the network’s primary site may leave another shop’s queue untouched.
Check each store’s queue independently.
Read the first recurring failure
Group failed actions by hook and error instead of opening the newest one. Match a representative failure with PHP and integration logs.
A missing function points to plugin/version incompatibility; authentication errors to credentials; timeouts to an unknown external outcome; database deadlocks to concurrent writes.
Correct the common cause before clicking Retry on a large batch.
Check PHP workers and time limits
Queue runners need available PHP processes and memory. If every worker is occupied by slow requests, cron arrives but cannot progress.
Inspect hosting resource graphs, PHP fatals and worker saturation. Increase capacity only after identifying whether one action monopolises each worker.
Split custom bulk jobs into bounded items. One action should not import an entire catalogue or contact thousands of customers in a single request.
Inspect database locks and table health
Action Scheduler claims and logs work in MySQL. Slow queries, disk pressure or abandoned claims can reduce throughput.
Use database metrics and official Action Scheduler/WooCommerce tools for the installed versions. Back up before table maintenance.
Do not truncate action tables: history is needed for deduplication, audit and diagnosis.
Make callbacks idempotent
The same action can run again after a timeout. Payment, stock and fulfilment callbacks must recognise an operation already completed.
$order = wc_get_order( $order_id );
if ( ! $order ) {
throw new RuntimeException( 'Scheduled order unavailable' );
}
Validation is only the start; store a stable external reference and query uncertain outcomes before retrying. Never log API secrets or personal payloads.
Recover in controlled batches
Reconcile sensitive Failed/Pending actions with provider and order state. Repair the root cause, then run one low-risk action and verify its effects.
Process a bounded batch while monitoring completion rate, PHP, MySQL and external rate limits. Stop if duplicates or new failures appear.
Archive or cancel actions only when their business operation is proven obsolete.
Prevent another silent backlog
Set alerts on oldest Pending age, failure rate and queue growth rather than total historical actions. Test cron after migrations, PHP changes and security-rule updates.
Complete a controlled order and confirm its email, webhook, stock and external tasks finish once. Recurring WooCommerce care should treat queue latency as a transaction-health metric, not a housekeeping detail.