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
if (!wp_next_scheduled('my_hourly_event')) {
wp_schedule_event(time(), 'hourly', 'my_hourly_event');
}
add_action('my_hourly_event', 'my_function_to_run');define('DISABLE_WP_CRON', true);*/5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1Gotchas
- 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.
Related Tools
Platform Guides
Cron syntax for Linux, Kubernetes, AWS, and more
cPanel Cron Jobs Guide
How to add, edit, and troubleshoot cron jobs in cPanel: the Cron Jobs UI, email notification pitfalls, PHP path issues, and standard intervals.
systemd Timers vs Cron
How systemd timers work as a modern alternative to cron: OnCalendar syntax, unit file setup, and when timers are actually worth switching to.