{"slug":"wp-cron-management","title":"WordPress Cron and Scheduled Tasks","tags":["cron","wp-cron","scheduled-tasks","automation","server-cron"],"agent_summary":"WordPress WP-Cron: scheduling events with wp_schedule_event, custom intervals, disabling WP-Cron for real server cron (crontab), WP-CLI cron management, and deactivation cleanup.","trigger_phrases":["wordpress cron","wp-cron","wp_schedule_event","scheduled tasks wordpress","disable wp cron","server cron wordpress","wp cron event list"],"runnable":true,"markdown":"\nWP-Cron is a pseudo-cron that fires on page load. On production with consistent traffic, replace it with real server cron.\n\n## Schedule an Event\n\n```php\n// Register on plugin/theme activation\nif (!wp_next_scheduled('my_daily_cleanup')) {\n    wp_schedule_event(time(), 'daily', 'my_daily_cleanup');\n}\n\n// Hook the callback\nadd_action('my_daily_cleanup', 'run_daily_cleanup');\n\nfunction run_daily_cleanup() {\n    global $wpdb;\n    // Delete expired transients\n    $wpdb->query(\n        \"DELETE FROM {$wpdb->options}\n         WHERE option_name LIKE '_transient_timeout_%'\n         AND option_value < \" . time()\n    );\n}\n\n// Clean up on deactivation (IMPORTANT — don't leave orphan events)\nregister_deactivation_hook(__FILE__, function() {\n    wp_clear_scheduled_hook('my_daily_cleanup');\n});\n```\n\n## Custom Schedule Intervals\n\n```php\nadd_filter('cron_schedules', function($schedules) {\n    $schedules['every_15_minutes'] = [\n        'interval' => 900,\n        'display'  => 'Every 15 Minutes',\n    ];\n    $schedules['every_6_hours'] = [\n        'interval' => 21600,\n        'display'  => 'Every 6 Hours',\n    ];\n    return $schedules;\n});\n```\n\n## Replace WP-Cron With Real Server Cron\n\nStep 1 — Disable WP-Cron in wp-config.php:\n\n```php\ndefine('DISABLE_WP_CRON', true);\n```\n\nStep 2 — Add real cron job (runs every 15 minutes):\n\n```bash\n# Via crontab -e\n*/15 * * * * /usr/local/bin/wp cron event run --due-now \\\n  --path=/var/www/html --quiet\n\n# Or via PHP directly\n*/15 * * * * /usr/bin/php /var/www/html/wp-cron.php > /dev/null 2>&1\n```\n\n## WP-CLI Cron Management\n\n```bash\n# List all scheduled events\nwp cron event list\n\n# Run all due events immediately\nwp cron event run --due-now\n\n# Check when specific event runs next\nwp cron event list --fields=hook,next_run_gmt | grep my_daily_cleanup\n\n# Delete a stuck event\nwp cron event delete my_daily_cleanup\n\n# Test cron (simulates triggering)\nwp cron test\n```\n\n## Built-In WordPress Schedules\n\n| Interval | Slug | Seconds |\n|----------|------|---------|\n| Every hour | `hourly` | 3600 |\n| Twice daily | `twicedaily` | 43200 |\n| Daily | `daily` | 86400 |\n| Weekly | `weekly` | 604800 |\n","html":"<p>WP-Cron is a pseudo-cron that fires on page load. On production with consistent traffic, replace it with real server cron.</p>\n<h2>Schedule an Event</h2>\n<pre><code class=\"language-php\">// Register on plugin/theme activation\nif (!wp_next_scheduled('my_daily_cleanup')) {\n    wp_schedule_event(time(), 'daily', 'my_daily_cleanup');\n}\n\n// Hook the callback\nadd_action('my_daily_cleanup', 'run_daily_cleanup');\n\nfunction run_daily_cleanup() {\n    global $wpdb;\n    // Delete expired transients\n    $wpdb->query(\n        \"DELETE FROM {$wpdb->options}\n         WHERE option_name LIKE '_transient_timeout_%'\n         AND option_value &#x3C; \" . time()\n    );\n}\n\n// Clean up on deactivation (IMPORTANT — don't leave orphan events)\nregister_deactivation_hook(__FILE__, function() {\n    wp_clear_scheduled_hook('my_daily_cleanup');\n});\n</code></pre>\n<h2>Custom Schedule Intervals</h2>\n<pre><code class=\"language-php\">add_filter('cron_schedules', function($schedules) {\n    $schedules['every_15_minutes'] = [\n        'interval' => 900,\n        'display'  => 'Every 15 Minutes',\n    ];\n    $schedules['every_6_hours'] = [\n        'interval' => 21600,\n        'display'  => 'Every 6 Hours',\n    ];\n    return $schedules;\n});\n</code></pre>\n<h2>Replace WP-Cron With Real Server Cron</h2>\n<p>Step 1 — Disable WP-Cron in wp-config.php:</p>\n<pre><code class=\"language-php\">define('DISABLE_WP_CRON', true);\n</code></pre>\n<p>Step 2 — Add real cron job (runs every 15 minutes):</p>\n<pre><code class=\"language-bash\"># Via crontab -e\n*/15 * * * * /usr/local/bin/wp cron event run --due-now \\\n  --path=/var/www/html --quiet\n\n# Or via PHP directly\n*/15 * * * * /usr/bin/php /var/www/html/wp-cron.php > /dev/null 2>&#x26;1\n</code></pre>\n<h2>WP-CLI Cron Management</h2>\n<pre><code class=\"language-bash\"># List all scheduled events\nwp cron event list\n\n# Run all due events immediately\nwp cron event run --due-now\n\n# Check when specific event runs next\nwp cron event list --fields=hook,next_run_gmt | grep my_daily_cleanup\n\n# Delete a stuck event\nwp cron event delete my_daily_cleanup\n\n# Test cron (simulates triggering)\nwp cron test\n</code></pre>\n<h2>Built-In WordPress Schedules</h2>\n<p>| Interval | Slug | Seconds |\n|----------|------|---------|\n| Every hour | <code>hourly</code> | 3600 |\n| Twice daily | <code>twicedaily</code> | 43200 |\n| Daily | <code>daily</code> | 86400 |\n| Weekly | <code>weekly</code> | 604800 |</p>\n"}