# Fix WordPress Cron Not Working
Scheduled posts aren't publishing. Automatic backups aren't running. Plugin scheduled tasks are failing. WordPress cron isn't working, and your automated tasks have stopped.
WordPress uses a pseudo-cron system called wp-cron. Unlike real system cron, it only runs when someone visits your site. This has limitations: low-traffic sites miss schedules, high-traffic sites cause performance problems, and certain configurations block wp-cron entirely.
Diagnose the Problem
Check Scheduled Tasks
```bash # List all scheduled cron jobs wp cron event list
# Check for overdue tasks wp cron event list --fields=hook,next_run,status --status=pending
# Check specific scheduled time wp cron event list --fields=hook,next_run --format=table ```
Test Cron Execution
```bash # Run cron manually wp cron event run --due-now
# Run all cron events wp cron event run --all
# Test specific hook wp cron event run wp_version_check ```
Check if wp-cron.php is Accessible
```bash # Test wp-cron.php directly curl -I https://yourdomain.com/wp-cron.php
# Should return 200 OK, not 403 or 404 ```
Check wp-config Constants
# Check if cron is disabled
grep -i "DISABLE_WP_CRON\|ALTERNATE_WP_CRON" wp-config.phpIf define('DISABLE_WP_CRON', true); exists, wp-cron won't run automatically.
Common Causes and Fixes
1. Low Traffic Site
On low-traffic sites, cron only runs when someone visits. If no one visits, scheduled tasks don't run.
Solution: Set up a real system cron
```bash # Edit crontab crontab -e
# Add this line to run wp-cron every 5 minutes */5 * * * * curl -s https://yourdomain.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
# Or using WP-CLI (preferred) */5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now --quiet ```
Then disable the pseudo-cron:
// Add to wp-config.php
define('DISABLE_WP_CRON', true);2. wp-cron.php Blocked
Security plugins or server rules may block wp-cron.php.
Check .htaccess for blocks:
grep -i "wp-cron" .htaccessCheck if blocked by security plugin:
wp plugin list --status=activeTemporarily deactivate security plugins:
wp plugin deactivate wordfence
wp plugin deactivate iThemes-securityCheck server firewall:
curl -I https://yourdomain.com/wp-cron.phpIf blocked, whitelist wp-cron.php in your firewall or security plugin.
3. PHP Timeout on Cron
Long-running cron jobs may timeout.
Increase PHP timeout:
// In wp-config.php
set_time_limit(300);Or in php.ini:
max_execution_time = 3004. Memory Limit
Cron jobs need memory too.
// In wp-config.php
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');5. Missed Scheduled Posts
Posts scheduled but never published.
```bash # Check for missed schedule hook wp cron event list | grep -i miss
# Run missed schedule check wp cron event run publish_future_post
# Check scheduled posts wp post list --post_status=future --fields=ID,post_title,post_date ```
Manual fix for missed posts:
# Get all future posts that should have been published
wp post list --post_status=future --field=ID | while read post_id; do
wp post update $post_id --post_status=publish
doneInstall Missed Schedule plugin:
wp plugin install missed-schedule --activate6. Cron Locked
WordPress uses a transient to prevent concurrent cron runs. If this gets stuck, cron won't run.
```bash # Check if cron is locked wp transient get doing_cron
# Delete the lock wp transient delete doing_cron
# Now run cron wp cron event run --due-now ```
7. WP-CLI Cron vs HTTP Cron
WP-CLI cron doesn't require HTTP access.
Set up WP-CLI system cron:
```bash # Edit crontab crontab -e
# Run WP-CLI cron every 5 minutes */5 * * * * cd /var/www/html && wp cron event run --due-now --quiet --user=1 ```
Disable HTTP cron:
// In wp-config.php
define('DISABLE_WP_CRON', true);8. Server Timezone Mismatch
If server time doesn't match WordPress time, schedules appear incorrect.
```bash # Check server time date
# Check WordPress time wp option get timezone_string wp option get gmt_offset
# Check WordPress time wp eval 'echo current_time("mysql") . "\n";' ```
Set WordPress timezone:
wp option update timezone_string "America/New_York"Debug Cron Issues
Enable Cron Debugging
```php // In wp-config.php define('WP_DEBUG', true); define('WP_DEBUG_LOG', true);
// Add custom cron debugging add_action('init', function() { if (defined('DOING_CRON') && DOING_CRON) { error_log('Cron started at: ' . date('Y-m-d H:i:s')); } }); ```
Log Cron Execution
# Tail the debug log during cron
tail -f wp-content/debug.logCheck Cron Schedules
```bash # List registered schedules wp eval ' $schedules = wp_get_schedules(); foreach ($schedules as $name => $schedule) { echo "$name: {$schedule["interval"]} seconds ({$schedule["display"]})\n"; } '
# Check specific scheduled event wp cron event list --fields=hook,schedule,next_run ```
Monitor Cron Execution
Add logging to specific hooks:
```php // In functions.php or custom plugin add_action('wp_scheduled_delete', function() { error_log('wp_scheduled_delete ran at: ' . date('Y-m-d H:i:s')); });
add_action('publish_future_post', function($post_id) { error_log("Published scheduled post ID: $post_id at: " . date('Y-m-d H:i:s')); }); ```
Optimize Cron Performance
Disable Unnecessary Cron Jobs
```bash # List all scheduled events wp cron event list --fields=hook,schedule
# Remove unnecessary events wp cron event delete wp_update_plugins wp cron event delete wp_update_themes ```
Consolidate Cron Jobs
If you have many plugins scheduling their own crons:
```php // Clear all plugin crons and consolidate // Then set up a single system cron that triggers a custom action
// Remove plugin crons wp_clear_scheduled_hook('plugin_daily_task'); wp_clear_scheduled_hook('plugin_hourly_task');
// Add consolidated schedule add_action('my_daily_maintenance', function() { do_action('plugin_daily_task'); // Other daily tasks });
wp_schedule_event(time(), 'daily', 'my_daily_maintenance'); ```
Use Alternative Cron Method
If wp-cron.php isn't working via HTTP:
// In wp-config.php
define('ALTERNATE_WP_CRON', true);This uses a redirect method instead of spawning a separate process.
Check Specific Plugin Crons
WooCommerce
```bash # List WooCommerce scheduled actions wp wc tool list --field=name
# Run WooCommerce scheduled actions wp action-scheduler run
# Check pending actions wp action-scheduler list --status=pending ```
Backup Plugins
```bash # UpdraftPlus wp cron event list | grep updraft
# BackWPup wp cron event list | grep backwpup
# Run backup manually wp cron event run backwpup_cron ```
SEO Plugins
```bash # Yoast SEO wp cron event list | grep yoast
# Rank Math wp cron event list | grep rankmath ```
System Cron Setup Examples
Basic HTTP Cron
*/5 * * * * wget -q -O - https://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1WP-CLI Cron (Recommended)
*/5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now --quietWith Logging
*/5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now >> /var/log/wp-cron.log 2>&1Multiple Sites (Multisite)
*/5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now --url=https://site1.com --quiet
*/5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now --url=https://site2.com --quietVerification
After fixing cron:
```bash # Test cron runs wp cron event run --due-now
# Check for missed posts wp post list --post_status=future
# Check cron events are scheduled wp cron event list --status=pending
# Run test schedule wp cron event schedule test_event '+5 minutes' wp cron event list | grep test_event ```
Quick Troubleshooting Checklist
- 1.[ ] Check if DISABLE_WP_CRON is set
- 2.[ ] Test wp-cron.php accessibility via curl
- 3.[ ] Delete stuck cron lock transient
- 4.[ ] Check server timezone matches WordPress timezone
- 5.[ ] Verify PHP memory and time limits
- 6.[ ] Check for security plugin blocks
- 7.[ ] Set up system cron for reliability
- 8.[ ] Monitor cron execution in debug.log
WordPress cron is fragile by design. The solution is almost always to set up a proper system cron that triggers wp-cron.php on a reliable schedule, then disable the pseudo-cron for consistent, predictable task execution.