WP-Cron does not run continuously. WordPress checks due events on page loads, so a low-traffic site can publish a scheduled post late even when nothing is broken.

Start with evidence and the smallest reversible change; work on staging when possible, preserve the logs and rollback material if production is already down, and keep the objective specific: understand traffic-triggered WP-Cron, inspect overdue events, remove duplicate scheduling, and decide when a real system scheduler is appropriate.

What the symptom narrows down

  • No request arrives near the scheduled time, or DISABLE_WP_CRON is set without a working system cron.
  • Loopback requests fail, preventing the spawned cron request.
  • A slow or failing callback blocks later work or schedules duplicate events.

The branches are ordered to protect the strongest evidence around this possibility: no request arrives near the scheduled time, or DISABLE_WP_CRON is set without a working system cron. The observed scope and logs—not a familiar-looking error screen—decide which one applies.

Integration failures happen at custody boundaries; wordPress can format a request successfully while DNS, TLS, a proxy, remote service, authentication layer, or receiving provider rejects the next step; record what each boundary accepted—not just what the WordPress screen announced; in this guide, the practical goal is to understand traffic-triggered WP-Cron, inspect overdue events, remove duplicate scheduling, and decide when a real system scheduler is appropriate.

Evidence to collect before the fix

  1. Run wp cron event list and compare due times, hooks, and recurrence.
  2. Check the DISABLE_WP_CRON constant and hosting scheduler configuration.
  3. Test loopbacks and run one due hook manually on staging with logging.
  4. Search plugin code for activation/deactivation scheduling and wp_next_scheduled.

The sequence moves from observation toward intervention. Preserve the result of the final check—search plugin code for activation/deactivation scheduling and wp_next_scheduled—because it provides a useful comparison after the repair.

Inspect due events before adding another scheduler

List overdue hooks and confirm whether WordPress cron spawning is disabled. Run one named callback on staging before changing the system scheduler.

wp cron event list --fields=hook,next_run_gmt,next_run_relative,recurrence
wp config get DISABLE_WP_CRON --type=constant
wp cron event run VERIFIED_HOOK --due-now

Interpretation and safety: Replace VERIFIED_HOOK with an observed hook. If DISABLE_WP_CRON is true, verify that exactly one external scheduler calls wp-cron.php.

A bounded staging experiment

Begin with the first plausible cause: no request arrives near the scheduled time, or DISABLE_WP_CRON is set without a working system cron. Before changing state, write down what would confirm it and run the first read-only check: run wp cron event list and compare due times, hooks, and recurrence.

If the result supports that cause, try one bounded repair on staging: for timing-sensitive or low-traffic sites, call wp-cron.php from a protected system scheduler at a measured interval. If evidence from “Run wp cron event list and compare due times, hooks, and recurrence” points elsewhere, keep this layer unchanged and move to the next check. That small decision log is far easier to audit than several simultaneous edits.

Apply fixes in the safest order

  1. For timing-sensitive or low-traffic sites, call wp-cron.php from a protected system scheduler at a measured interval.
  2. Repair loopback failures when using traffic-triggered WP-Cron.
  3. Make callbacks bounded and idempotent; unschedule duplicates during plugin cleanup.

Before applying “For timing-sensitive or low-traffic sites, call wp-cron.php from a protected system scheduler at a measured interval,” name its rollback point and the evidence that will count as success. Afterward, repeat the original request and specifically check whether you can schedule a harmless event and observe its actual run time and log; a changed symptom at that point is new evidence, not permission to make several more changes at once.

Prove recovery

  • Schedule a harmless event and observe its actual run time and log.
  • Confirm one recurring event exists per intended hook/arguments.
  • Monitor duration and failure so backlog is visible.

One successful refresh is not closure. Keep the incident open until you can also confirm one recurring event exists per intended hook/arguments, adjacent paths have not regressed, temporary diagnostics are gone, and another operator can explain what changed.

Prepare a useful escalation if the boundary is outside your control

A useful escalation contains the UTC timestamp, destination host or route, sanitized request/response headers, status and application error code, correlation ID, retry behavior, and the source IP when relevant; never send live credentials in a ticket; include the result of this first observation: run wp cron event list and compare due times, hooks, and recurrence.

State what was tested, including the result of “Run `wp cron event list` and compare due times, hooks, and recurrence,” and what changed between attempts; evidence tied to that observation is safer and more actionable than granting broad access or sending an unnecessary full database export.

Shortcuts that create a second incident

  • Do not trigger wp-cron.php from several schedulers simultaneously.
  • Do not assume a due event disappeared because its callback succeeded; inspect the callback’s outcome.

Incident handoff

ScopeDiagnose WordPress Missed Schedule and Delayed WP-Cron Events · URL · role · first/last occurrence
EvidenceStatus · request ID · first relevant log entry
ChangeOne action · backup/rollback point · operator
ProofOriginal reproduction · adjacent paths · monitoring window

Primary references

Editorial note: The scenario above illustrates how to approach “For timing-sensitive or low-traffic sites, call wp-cron.php from a protected system scheduler at a measured interval”; it is a documented example, not a claim about a reader’s server, so verify the cited documentation, take the appropriate backup, and follow the real environment’s access and change-control rules.