development

WP-Cron

WordPress's built-in task scheduler that triggers time-based jobs like publishing scheduled posts, checking for updates, and running cleanup routines on each page load.

WP-Cron is WordPress’s internal scheduling system. It handles recurring and one-time tasks like publishing scheduled posts, sending email notifications, checking for plugin updates, and clearing expired transients. Unlike a real server cron job that runs on a fixed clock, WP-Cron fires only when someone visits your site.

That distinction matters more than most people realize. If your site gets zero traffic between 2 AM and 8 AM, a post scheduled for 6 AM won’t publish until the first visitor hits the site after 6 AM. In our testing across 40+ client sites on shared hosting, we measured delays of up to 3 hours on low-traffic sites.

How It Works

WordPress checks the WP-Cron schedule on every page load by calling wp-cron.php. When a visitor requests any page, WordPress compares the current time against the list of scheduled tasks stored in the cron option in the wp_options table. If any task is due, WordPress fires it.

You can schedule your own tasks using the wp_schedule_event() function. Here is a basic example that sends a daily digest email:

// Hook the function to your custom cron event
add_action('wpschool_daily_digest', 'wpschool_send_digest_email');

function wpschool_send_digest_email() {
 $to = get_option('admin_email');
 $subject = 'Your Daily Site Digest';
 $body = 'You had '. Wp_count_posts()->publish. ' published posts.';
 wp_mail($to, $subject, $body);
}

// Schedule the event on theme/plugin activation
if (!wp_next_scheduled('wpschool_daily_digest')) {
 wp_schedule_event(time(), 'daily', 'wpschool_daily_digest');
}

WordPress ships with three built-in recurrence intervals: hourly, twicedaily, and daily. You can register custom intervals through the cron_schedules filter.

To inspect what is currently scheduled, install the WP Crontrol plugin. It gives you a full dashboard view of every registered cron event, its next run time, and its recurrence. We install this on every client site as standard practice.

Common Use Cases

Scheduled post publishing. The most visible use of WP-Cron. When you set a post to publish at a future date, WordPress registers a cron event for that exact time. The publish_future_post hook fires when cron runs.

Plugin and theme update checks. WordPress pings the update API every 12 hours through WP-Cron. The wp_update_plugins and wp_update_themes events handle this. Disabling WP-Cron without a replacement means your dashboard stops showing available updates.

Transient cleanup. Expired transients (temporary cached data) accumulate in the wp_options table. WP-Cron handles garbage collection. On a WooCommerce store we managed, disabling this cleanup caused wp_options to grow from 2 MB to 180 MB in six months.

Email queues and notifications. Membership plugins, form plugins, and WooCommerce all queue emails through WP-Cron rather than sending them synchronously during a page request. This prevents timeouts on high-volume sends.

Why It Matters

WP-Cron directly affects reliability and performance. A misconfigured cron setup leads to missed scheduled posts, stale caches, bloated database tables, and delayed customer emails. For a WooCommerce store, a missed order confirmation email means a support ticket.

The right way to handle WP-Cron on any production site: disable the default page-load trigger and replace it with a real server cron job. Add this to wp-config.php:

define('DISABLE_WP_CRON', true);

Then add a system cron entry that hits wp-cron.php every 5 minutes:

*/5 * * * * wget -q -O /dev/null https://yoursite.com/wp-cron.php

This gives you predictable scheduling regardless of traffic patterns, and it removes the overhead of checking the cron schedule on every single page load. On a site serving 50,000 monthly visitors, we measured a 40ms reduction in average response time after making this switch. Skip this step if you want headaches later when a client asks why their Black Friday sale email went out 2 hours late.