# 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

bash
# Check if cron is disabled
grep -i "DISABLE_WP_CRON\|ALTERNATE_WP_CRON" wp-config.php

If 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:

php
// 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:

bash
grep -i "wp-cron" .htaccess

Check if blocked by security plugin:

bash
wp plugin list --status=active

Temporarily deactivate security plugins:

bash
wp plugin deactivate wordfence
wp plugin deactivate iThemes-security

Check server firewall:

bash
curl -I https://yourdomain.com/wp-cron.php

If 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:

php
// In wp-config.php
set_time_limit(300);

Or in php.ini:

ini
max_execution_time = 300

4. Memory Limit

Cron jobs need memory too.

php
// 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:

bash
# 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
done

Install Missed Schedule plugin:

bash
wp plugin install missed-schedule --activate

6. 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:

php
// 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:

bash
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

bash
# Tail the debug log during cron
tail -f wp-content/debug.log

Check 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:

php
// 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

bash
*/5 * * * * wget -q -O - https://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

WP-CLI Cron (Recommended)

bash
*/5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now --quiet

With Logging

bash
*/5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now >> /var/log/wp-cron.log 2>&1

Multiple Sites (Multisite)

bash
*/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 --quiet

Verification

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. 1.[ ] Check if DISABLE_WP_CRON is set
  2. 2.[ ] Test wp-cron.php accessibility via curl
  3. 3.[ ] Delete stuck cron lock transient
  4. 4.[ ] Check server timezone matches WordPress timezone
  5. 5.[ ] Verify PHP memory and time limits
  6. 6.[ ] Check for security plugin blocks
  7. 7.[ ] Set up system cron for reliability
  8. 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.