A WooCommerce Action Scheduler queue can process thousands of actions per hour while a small group of renewals, webhooks, emails, or imports waits far beyond its service window. Global pending count and runner activity look healthy because a noisy hook consumes claims as fast as workers can open them. Starvation detection compares age and throughput by group, hook, priority, and business record instead of averaging the whole queue.
Use this when some WooCommerce emails, renewals, webhooks, imports, or cleanup jobs are late even though Action Scheduler runners appear active.
Quick answer
Snapshot pending and in-progress actions by group and hook, then calculate oldest scheduled age, p95 wait, claim-to-start time, run duration, failure rate, and share of worker capacity. Alert when one group exceeds its business time budget while another group dominates claims. Prove idempotency before replaying or changing concurrency.
What to check first
- Export action ID, hook, group, priority, status, scheduled time, claim ID, attempts, last error, and related order or subscription ID.
- Calculate pending count, oldest age, p95 wait, starts per minute, duration, and failure rate per group and hook.
- Compare runner count, batch size, claim timeout, WP-Cron traffic, CLI runners, database locks, and external API latency.
- Map each group to a business deadline such as payment retry, renewal email, stock release, or conversion upload.
- Confirm affected hooks are idempotent before manual runs, retries, priority changes, or extra workers.
Why this usually happens
- Claim order and priority can let a continuous high-volume hook occupy available runner batches.
- A slow external API holds workers long enough for unrelated groups to age.
- Global dashboards hide a low-volume group because its count is small relative to the dominant workload.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
group,hook,pending,oldest_age_min,p95_wait_min,starts_per_min,budget
renewals,process_subscription,18,47,39,0.2,10
imports,sync_catalog,8420,6,4,31.4,60
webhooks,deliver_webhook,204,12,9,4.8,15
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Capture a per-group and per-hook queue snapshot before manual intervention. | Export action ID, hook, group, priority, status, scheduled time, claim ID, attempts, last error, and related order or subscription ID. | Every critical group starts within its documented business time budget. |
| Identify the dominant claim consumer and the starved business group. | Calculate pending count, oldest age, p95 wait, starts per minute, duration, and failure rate per group and hook. | The dominant hook no longer consumes an unsafe share of claims or worker time. |
| Correct permanent failures or external latency before adding capacity. | Compare runner count, batch size, claim timeout, WP-Cron traffic, CLI runners, database locks, and external API latency. | Added capacity does not increase duplicate payments, emails, webhooks, stock changes, or lock waits. |
| Tune runner, batch, priority, or group isolation on staging with idempotent fixtures. | Map each group to a business deadline such as payment retry, renewal email, stock release, or conversion upload. | Alerts identify group, hook, oldest action, business record, owner, and recommended next check. |
Decision rule
Declare starvation when a group exceeds its service budget while runners continue processing other groups. Do not replay or scale until the affected hook's duplicate behavior is understood.
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Balanced queue | Two groups below runner capacity | Both groups start within their service budgets |
| Noisy hook | One high-volume slow hook plus a low-volume renewal group | Detector flags renewal age even while total throughput remains high |
| Failed action | Permanent payload error in one group | Failure is separated from pending starvation and assigned to the correct owner |
| Capacity increase | Controlled extra runner on staging | Wait time improves without duplicate side effects or database lock growth |
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Capture a per-group and per-hook queue snapshot before manual intervention.
- Identify the dominant claim consumer and the starved business group.
- Correct permanent failures or external latency before adding capacity.
- Tune runner, batch, priority, or group isolation on staging with idempotent fixtures.
- Deploy gradually and alert on oldest age and business deadline, not pending count alone.
Production verification checklist
- Every critical group starts within its documented business time budget.
- The dominant hook no longer consumes an unsafe share of claims or worker time.
- Added capacity does not increase duplicate payments, emails, webhooks, stock changes, or lock waits.
- Alerts identify group, hook, oldest action, business record, owner, and recommended next check.
What to tell the client or owner
Give the owner the affected versions, exact fixture, stable IDs, UTC timeline, before and after evidence, decision, rollback point, unresolved risks, and next review date.
Mistakes to avoid
- Do not change several production layers at once. Preserve the failing evidence and isolate one variable per test.
- Do not use a successful status or screen message as the only proof. Verify the business outcome and the underlying record.
- Do not leave debug logging, broad credentials, test orders, or temporary exceptions active after the review.
- Do not close the incident without recording the fixture, timestamps, owner, result, and rollback point.
Questions teams ask during testing
Can this be tested on staging?
Start on staging with production-like versions, cache, data shape, and integrations. Finish with one controlled production fixture when the result depends on real routing, provider, or edge behavior.
What evidence should be retained?
Keep the smallest useful set: stable IDs, UTC timestamps, sanitized request or log excerpts, expected result, actual result, version inventory, and the final verification.
When should the change be rolled back?
Roll back when a core revenue, privacy, security, or publishing path fails and the cause cannot be isolated inside the approved maintenance window.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, repair a WooCommerce background queue.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Helpful references