preloader

WP Crontrol: Understanding and Fixing WordPress Cron Problems

WordPress cron (WP-Cron) is not real cron. It is a visit-triggered system: scheduled tasks run when a visitor loads a page, not at a fixed time. On low-traffic sites, scheduled tasks may run hours late. On high-traffic sites, they may run multiple times simultaneously. WP Crontrol makes WP-Cron transparent and debuggable – and helps you set up real server cron to replace it.

How WP-Cron Actually Works

When WordPress generates any page, it checks whether any scheduled events are due. If yes, it spawns an HTTP request to wp-cron.php to run them. This has several implications:

  • If no one visits your site, no scheduled tasks run – posts stay scheduled but do not publish
  • The HTTP request to wp-cron.php is non-blocking but still consumes server resources on every page load
  • High traffic means many simultaneous cron checks – tasks may fire multiple times if not written with concurrency in mind
  • Server-level firewalls blocking loopback HTTP requests break WP-Cron entirely

Reading WP Crontrol

Go to Tools -> Cron Events. WP Crontrol shows every scheduled event with its next run time, schedule (once, hourly, daily, custom), and the hook name. Events marked in red are overdue – they should have run but have not. This is the clearest diagnostic signal that WP-Cron is not functioning.

The Cron Schedules tab shows all registered schedules. Check here if you are adding custom schedules and want to confirm they registered correctly.

Adding a Custom Cron Event

Two parts: register the schedule interval and hook the action:

// Register a custom interval (every 15 minutes)
add_filter('cron_schedules', function($schedules) {{
    $schedules['every_15_minutes'] = array(
        'interval' => 900,
        'display'  => 'Every 15 Minutes',
    );
    return $schedules;
}});

// Schedule the event on plugin/theme activation
function my_plugin_activate() {{
    if (!wp_next_scheduled('my_custom_cron_hook')) {{
        wp_schedule_event(time(), 'every_15_minutes', 'my_custom_cron_hook');
    }}
}}
register_activation_hook(__FILE__, 'my_plugin_activate');

// The actual task
add_action('my_custom_cron_hook', function() {{
    // Your task here
    update_option('last_cron_run', current_time('mysql'));
}});

// Clean up on deactivation
function my_plugin_deactivate() {{
    $timestamp = wp_next_scheduled('my_custom_cron_hook');
    wp_unschedule_event($timestamp, 'my_custom_cron_hook');
}}
register_deactivation_hook(__FILE__, 'my_plugin_deactivate');

Need this built properly? Describe the project and get a free estimate.

Setting Up Real Server Cron

Replace WP-Cron’s visit-triggered system with a real server cron job that runs on a fixed schedule. This is the right solution for production sites.

Step 1: disable WP-Cron’s visit-triggered behaviour by adding to wp-config.php:

define('DISABLE_WP_CRON', true);

Step 2: add a real server cron job. Access your server’s crontab (cPanel -> Cron Jobs, or crontab -e via SSH):

# Run WordPress cron every minute
* * * * * cd /path/to/wordpress && php wp-cron.php > /dev/null 2>&1

# Or use WP-CLI if available (recommended):
* * * * * cd /path/to/wordpress && wp cron event run --due-now > /dev/null 2>&1

After setting up server cron, reload WP Crontrol and verify events are running on time. Events should show next run times updating regularly rather than stale overdue times.

Debugging Cron Jobs That Are Not Running

If WP Crontrol shows events as overdue and server cron is set up correctly, work through this checklist:

  • Verify the cron job is actually running: add > /tmp/cron.log 2>&1 to the cron command and check the log file
  • Check PHP path: php in the cron command may point to a different PHP version than your site uses. Use the full path: /usr/local/bin/php8.2
  • Verify the WordPress path in the cron command is correct
  • Check for PHP errors in wp-cron.php execution by temporarily removing > /dev/null 2>&1
  • Confirm the hook has a callback registered – WP Crontrol shows the event but the hook may have no add_action registered for it

Keep Reading

Previous Post Using Query Monitor to Debug WordPress Hooks and Plugin Conflicts Next Post Writing Custom WordPress Cron Jobs with WP Crontrol

Need Help With Your WordPress Site?

If you need help with WordPress fixes, plugin issues, theme customization, or development work, feel free to get in touch.

Get a Free Estimate