/
Application Framework

WordPress WP-Cron Guide

WordPress's built-in scheduling system, WP-Cron, is not a real cron daemon at all — it's a pseudo-cron that piggybacks on site traffic. Every page load triggers a check for due scheduled tasks (post publishing, plugin maintenance, update checks), which works fine on busy sites but causes real, well-documented reliability problems on low-traffic ones.

Syntax Notes

WP-Cron events are scheduled with wp_schedule_event() using either a Unix timestamp plus a recurrence interval name ('hourly', 'daily', 'twicedaily', or a custom-registered interval) — there's no raw 5-field cron string in the native WordPress API, though plugins sometimes layer cron-like syntax on top.

Examples

Schedule a recurring event (PHP)
if (!wp_next_scheduled('my_hourly_event')) {
    wp_schedule_event(time(), 'hourly', 'my_hourly_event');
}
add_action('my_hourly_event', 'my_function_to_run');
Disable pseudo-cron in wp-config.php
define('DISABLE_WP_CRON', true);
Real system cron entry to replace it
*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1

Gotchas

  • On a low-traffic site, WP-Cron events simply don't fire until the next visitor loads a page — a scheduled post set for 3 AM might not actually publish until the first visitor arrives hours later, which is one of the most commonly reported WordPress scheduling bugs.
  • Every page load technically triggers a wp-cron.php check (even if nothing is due), adding a small but real performance overhead to every request — on high-traffic sites this can mean the pseudo-cron check runs far more often than necessary.
  • WP-Cron's built-in intervals are limited to hourly, twicedaily, and daily by default — anything more granular (like every 15 minutes) requires registering a custom interval via the cron_schedules filter, which many site owners don't realize is necessary.

Best Practices

  • For any production site where scheduling reliability matters, set DISABLE_WP_CRON to true and trigger wp-cron.php via a real system cron job every 1-5 minutes instead — this is the standard, widely-recommended fix.
  • When adding a real system cron entry, use wget or curl with -s (silent) and discard output, and consider WP-CLI's `wp cron event run --due-now` as a cleaner alternative to hitting the HTTP endpoint directly.
  • Audit scheduled events periodically with WP-CLI (`wp cron event list`) — plugins that fail to clean up their scheduled events after deactivation are a common source of orphaned, silently-accumulating WP-Cron entries.

Frequently Asked Questions

Is WP-Cron the same as real Linux cron?
No — it's a pseudo-cron system triggered by page visits, not a background daemon. It only checks for due events when someone (or something) loads a page on the site, which is fundamentally different from real cron's time-based daemon.
Why did my scheduled WordPress post publish late?
Most likely because no one visited the site around the scheduled time — WP-Cron's check only runs on page load, so a post scheduled for 3 AM on a low-traffic site may not actually publish until the next visitor arrives.
How do I fix unreliable WP-Cron scheduling?
Disable the pseudo-cron (DISABLE_WP_CRON in wp-config.php) and set up a real system cron job (or a server-level scheduled task) to hit wp-cron.php every few minutes instead — this guarantees checks happen on a real schedule regardless of traffic.