WordPress Cron API
Understanding WP-Cron
WP-Cron is WordPress’s task scheduling system used to run automated tasks such as:
publishing scheduled posts
checking for plugin/theme updates
sending scheduled emails
cleaning temporary data
running background jobs
Unlike a traditional Linux cron daemon, WP-Cron:
runs only when a page loads
does not run continuously
executes missed tasks immediately on the next page load
This system is often called pseudo-cron or false cron.
Key characteristics:
triggered by site traffic
scheduled events stored in the wp_options table
events executed using action hooks
Core file responsible for execution:
wp-cron.php
How WP-Cron Works Internally
Process flow:
WordPress loads a page.
WordPress checks scheduled tasks in
wp_options.If an event time has passed:
- WordPress calls
wp-cron.php.
- WordPress calls
WordPress triggers the hook associated with the event.
Developers attach functions to that hook.
Example flow:
schedule event → event stored → time reached → page load → wp-cron triggered → action hook fired → function executed
Core Cron API Functions
Important functions used in plugin development.
Schedule a single event
wp_schedule_single_event()
Runs once at a specific timestamp.
Schedule recurring event
wp_schedule_event()
Runs repeatedly based on interval.
Check if event already exists
wp_next_scheduled()
Prevents duplicate events.
Remove scheduled event
wp_unschedule_event()
Deletes a specific scheduled event.
Clear scheduled hook
wp_clear_scheduled_hook()
Removes all events for a hook.
Scheduling Recurring Events in a Plugin
Typical pattern for plugins.
Step 1: Register cron event on plugin activation
register_activation_hook(__FILE__, 'myplugin_activate');
function myplugin_activate() {
if (!wp_next_scheduled('myplugin_cron_event')) {
wp_schedule_event(
time(),
'hourly',
'myplugin_cron_event'
);
}
}
Explanation:
time()→ start timehourly→ recurrence intervalmyplugin_cron_event→ hook name
Step 2: Attach function to the cron hook
add_action('myplugin_cron_event', 'myplugin_run_cron');
function myplugin_run_cron() {
// Your scheduled task here
error_log('My Plugin Cron Ran');
}
This function executes when WP-Cron runs the event.
Step 3: Clear cron event on plugin deactivation
Important to avoid orphan cron jobs.
register_deactivation_hook(__FILE__, 'myplugin_deactivate');
function myplugin_deactivate() {
wp_clear_scheduled_hook('myplugin_cron_event');
}
Scheduling a One-Time Task
Useful for delayed background jobs.
Example: send email after 10 minutes.
wp_schedule_single_event(
time() + 600,
'myplugin_send_email'
);
Attach handler:
add_action('myplugin_send_email', 'myplugin_email_function');
function myplugin_email_function() {
wp_mail(
'user@example.com',
'Notification',
'Your scheduled email.'
);
}
Checking if a Cron Event Exists
Avoid scheduling duplicates.
if (!wp_next_scheduled('myplugin_cron_event')) {
wp_schedule_event(time(), 'daily', 'myplugin_cron_event');
}
Without this check, WordPress may schedule multiple identical events.
Removing Specific Cron Event
If you know timestamp.
$timestamp = wp_next_scheduled('myplugin_cron_event');
if ($timestamp) {
wp_unschedule_event($timestamp, 'myplugin_cron_event');
}
WordPress Default Cron Intervals
Default intervals available:
| Interval | Time |
|---|---|
| hourly | 3600 seconds |
| twicedaily | 12 hours |
| daily | 24 hours |
Creating Custom Cron Intervals
Developers often need custom schedules.
Example: every 5 minutes.
add_filter('cron_schedules', 'myplugin_custom_cron_interval');
function myplugin_custom_cron_interval($schedules) {
$schedules['five_minutes'] = array(
'interval' => 300,
'display' => 'Every Five Minutes'
);
return $schedules;
}
Use it when scheduling:
wp_schedule_event(time(), 'five_minutes', 'myplugin_cron_event');
Viewing Scheduled Events
You can inspect cron events using:
Plugins:
WP Crontrol
Query Monitor
Or via WP-CLI:
wp cron event list
Common Cron API Use Cases
Automatic cleanup
delete_expired_transients();
Scheduled email sending
wp_mail()
Database maintenance
$wpdb->query("DELETE FROM table WHERE status='expired'");
Scheduled API synchronization
wp_remote_get()
Scheduled backups
Trigger backup scripts periodically.
Debugging WP-Cron
Check if WP-Cron is working.
define('DISABLE_WP_CRON', false);
Log cron execution:
error_log('Cron executed at: ' . current_time('mysql'));
Check scheduled tasks:
wp cron event list
Limitations of WP-Cron
Because WP-Cron depends on traffic:
Problems occur when:
low-traffic websites
high-precision scheduling required
background tasks need reliability
Possible issues:
delayed execution
tasks pile up
inconsistent timing
Using Real Linux Cron Instead of WP-Cron
Better solution for production sites.
Step 1: Disable WordPress pseudo cron
Edit wp-config.php.
define('DISABLE_WP_CRON', true);
Step 2: Add system cron job
Using crontab.
crontab -e
Add:
*/5 * * * * wget -q -O - https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
Meaning:
*/5 * * * *
run every 5 minutes
Alternative using PHP:
*/5 * * * * php /path/to/wordpress/wp-cron.php
Advantages:
runs on schedule
independent of site traffic
better for production servers
Best Practices for Plugin Cron Jobs
Always follow these principles:
Prevent duplicate scheduling
wp_next_scheduled()
Remove cron jobs on plugin deactivation
register_deactivation_hook()
Keep cron tasks lightweight
Heavy operations should be:
chunked
queued
processed gradually
Use transient or option locks
Prevent overlapping executions.
Example:
if (get_transient('myplugin_cron_lock')) {
return;
}
set_transient('myplugin_cron_lock', true, 300);
Example – Real Plugin Cron Task
Complete working example.
add_action('init', 'myplugin_schedule_event');
function myplugin_schedule_event() {
if (!wp_next_scheduled('myplugin_daily_cleanup')) {
wp_schedule_event(
time(),
'daily',
'myplugin_daily_cleanup'
);
}
}
add_action('myplugin_daily_cleanup', 'myplugin_cleanup_function');
function myplugin_cleanup_function() {
global $wpdb;
$wpdb->query(
"DELETE FROM {$wpdb->prefix}my_table
WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)"
);
}