
Scheduled WordPress backups failing silently? WP-Cron is probably to blame. WordPress’s built-in cron system is visitor-triggered, not guaranteed to run, and often fails on low-traffic sites. This technical guide covers WP-Cron limitations, server cron setup, monitoring, and optimization techniques ensuring scheduled backups run reliably every time.
How WordPress WP-Cron Works
WordPress doesn’t use real cron. Instead, WP-Cron is a pseudo-cron system:
Visitor-Triggered: When someone visits your site, WordPress checks if any scheduled tasks are due. If yes, it spawns a background HTTP request to run those tasks.
Not Guaranteed: If no one visits your site, scheduled tasks don’t run. Low-traffic sites or sites with aggressive caching skip cron execution.
Timing Imprecise: Tasks scheduled for 2:00 AM might run at 2:17 AM (when first visitor arrives after 2:00).
How It Works:
1. Visitor requests page
2. WordPress loads
3. WordPress checks: "Any scheduled tasks due?"
4. If yes: Spawn background request to wp-cron.php
5. Continue loading page for visitor
6. Background request executes scheduled tasks
Advantages: – Works everywhere (no server access needed) – No special hosting configuration required – Automatically scales with traffic
Disadvantages: – Not guaranteed to run – Timing imprecise – Can slow down page loads – May skip on cached pages – Unreliable for critical tasks like backups
Why WP-Cron Fails for Backups
Common scenarios where WP-Cron fails:
Low-Traffic Sites: Development sites, personal blogs, or internal tools with few visitors may go hours without triggering WP-Cron.
Page Caching: Full-page caching (WP Super Cache, W3 Total Cache, Cloudflare) bypasses WordPress entirely. Cached page serves without loading WordPress or checking cron.
Object Caching: Persistent object caching (Redis, Memcached) can cache cron checks, causing WordPress to think cron already ran.
PHP Execution Time Limits: Backup creation takes 2-5 minutes. If visitor’s request times out, background cron request also terminates, killing backup mid-process.
Memory Limits: Backups consume significant memory. Shared hosting’s 128-256 MB limit causes cron processes to crash.
Multiple Simultaneous Backups: Two visitors arrive simultaneously. WordPress spawns two cron processes. Both try creating backup. One fails or both create partial backups.
Example Failure: – Backup scheduled for 2:00 AM daily – Site uses caching, has low overnight traffic – No visitors between 2:00 AM – 8:00 AM – Cron finally triggered at 8:15 AM when first visitor arrives – Result: Backup runs during business hours instead of overnight, causing performance issues
Server Cron vs WP-Cron Comparison
WP-Cron: – Pros: Works everywhere, no setup needed, automatic – Cons: Unreliable, imprecise timing, visitor-dependent – Best for: Non-critical scheduled tasks, high-traffic sites
Server Cron (Real Cron): – Pros: Guaranteed execution, precise timing, visitor-independent – Cons: Requires server access, manual setup, not available on all hosts – Best for: Critical tasks like backups, low-traffic sites, precise scheduling
Recommendation: Disable WP-Cron and use server cron for sites with scheduled backups.
Disabling WP-Cron
First step: Disable WP-Cron in wp-config.php.
Edit wp-config.php (before /* That's all, stop editing! */ line):
define('DISABLE_WP_CRON', true);This prevents WordPress from automatically triggering cron on visitor requests.
Important: After disabling WP-Cron, scheduled tasks stop running until you set up server cron.
Setting Up Server Cron
Configure real cron to trigger WordPress tasks reliably.
cPanel Method
Most shared hosting uses cPanel:
- Log into cPanel
- Navigate to “Cron Jobs”
- Add New Cron Job:
- Minute: */15 (every 15 minutes)
- Hour: * (every hour)
- Day: * (every day)
- Month: * (every month)
- Weekday: * (every weekday)
- Command:
php /home/username/public_html/wp-cron.php
Replace /home/username/public_html/ with your actual WordPress path.
Alternative using wget:
*/15 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1Alternative using curl:
*/15 * * * * curl https://yoursite.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1Plesk Method
Plesk hosting setup:
- Log into Plesk
- Navigate to “Scheduled Tasks” or “Cron Jobs”
- Add Task:
- Schedule: Every 15 minutes
- Command:
php /var/www/vhosts/yourdomain.com/httpdocs/wp-cron.php
SSH Command Line Method
Direct cron configuration via SSH:
# Open crontab editor
crontab -e
# Add line (every 15 minutes):
*/15 * * * * php /var/www/html/wp-cron.php > /dev/null 2>&1
# Save and exitVerify cron is running:
crontab -lCron Syntax Explained
Cron timing format:
* * * * * command
│ │ │ │ │
│ │ │ │ └─── Day of week (0-7, Sunday = 0 or 7)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
Common Schedules:
Every 15 minutes:
*/15 * * * * php /path/to/wp-cron.phpEvery hour:
0 * * * * php /path/to/wp-cron.phpTwice daily (6 AM and 6 PM):
0 6,18 * * * php /path/to/wp-cron.phpDaily at 2 AM:
0 2 * * * php /path/to/wp-cron.phpWeekly (Sunday 3 AM):
0 3 * * 0 php /path/to/wp-cron.phpCron Frequency Recommendations
How often should cron run?
Every 5-15 Minutes: Recommended for most sites. Balances responsiveness with server load.
Every Hour: Sufficient if you only have daily backups scheduled. Saves server resources.
Every Minute: Overkill unless running high-frequency tasks. Creates unnecessary server load.
Backup-Specific: Match cron frequency to your most frequent backup schedule: – Hourly database backups: Run cron every 15 minutes – Daily full backups: Run cron every hour – Weekly backups only: Run cron once daily
Alternative Cron Services
Can’t access server cron? Use external cron services:
EasyCron
Setup: 1. Sign up at https://www.easycron.com 2. Add cron job: – URL: https://yoursite.com/wp-cron.php?doing_wp_cron – Frequency: Every 15 minutes 3. Enable monitoring and notifications
Pricing: Free tier: 100 executions/month. Paid: $0.99/month for 1,000 executions.
Webcron.org
Simple external cron service:
- Visit https://cron-job.org
- Create free account
- Add job URL:
https://yoursite.com/wp-cron.php?doing_wp_cron - Set schedule: Every 15 minutes
- Enable notifications
Pricing: Free
WP Crontrol Plugin + External Trigger
Use WP Crontrol plugin to view and manage schedules, combine with external HTTP cron service.
Monitoring Cron Execution
Verify cron runs successfully:
Check WordPress Cron Events
Install “WP Crontrol” plugin:
- Navigate to Tools → Cron Events
- View all scheduled events
- Check “Next Run” times
- Look for overdue events (red flag)
Enable Cron Logging
Add to wp-config.php:
define('WP_CRON_LOCK_TIMEOUT', 60);
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);Check debug.log for cron execution:
tail -f /path/to/wp-content/debug.logMonitor Backup Completion
Check Backup Copilot Pro dashboard: – View recent backup history – Check for “Failed” or “Skipped” backups – Verify backups running at scheduled times
Set Up Notifications
Configure email notifications: – Backup success/failure emails – Cron failure alerts – Cloud upload completion confirmations
Preventing Overlapping Cron Jobs
Multiple cron executions running simultaneously cause problems:
Symptoms: – Database locked errors – Memory exhaustion – Incomplete backups – Duplicate backup attempts
Solution – Add Lock Check:
function run_backup_with_lock() {
// Check if backup already running
$lock = get_transient('bkpc_backup_running');
if ($lock) {
error_log('Backup already running, skipping...');
return;
}
// Set lock (valid for 1 hour)
set_transient('bkpc_backup_running', true, 3600);
// Run backup
try {
bkpc_create_backup();
} finally {
// Always release lock
delete_transient('bkpc_backup_running');
}
}Cron Timeout: WordPress has built-in protection: WP_CRON_LOCK_TIMEOUT (default 60 seconds). Prevents new cron spawns if one is already running.
Memory and Timeout Optimization
Backups require resources:
Increase PHP Memory Limit (wp-config.php):
define('WP_MEMORY_LIMIT', '512M');
define('WP_MAX_MEMORY_LIMIT', '512M');Increase PHP Execution Time (functions.php or plugin):
@ini_set('max_execution_time', 600); // 10 minutes
@ini_set('memory_limit', '512M');Split Large Backups: Instead of one huge backup, split into: – Database backup (quick, 1-2 minutes) – File backup (slower, 5-10 minutes) – Run at different times to avoid timeouts
Database Lock Prevention
Backups read database extensively. Concurrent writes can cause locks.
Solution – Database Timeout Increase:
SET SESSION wait_timeout = 600;
SET SESSION interactive_timeout = 600;Backup During Low-Traffic Hours: Schedule backups 2-5 AM when few database writes occur.
Use Database-Only Backups During Peak: Quick database snapshots during business hours, full backups overnight.
Multiple Backup Schedules
Running multiple backup schedules simultaneously:
Stagger Schedules: – Full backup: Daily at 2:00 AM – Database backup: Hourly at :15 past hour (1:15, 2:15, 3:15…) – File backup: Weekly Sunday 3:00 AM
This prevents conflicts.
Priority System: If two backups due simultaneously:
function prioritize_backup_execution($schedules) {
usort($schedules, function($a, $b) {
$priority = ['database' => 1, 'full' => 2, 'files' => 3];
return $priority[$a['type']] - $priority[$b['type']];
});
return $schedules;
}Security Considerations
Cron endpoints should be protected:
Authenticate Cron Requests:
// In wp-config.php
define('ALTERNATE_WP_CRON', true);
// In cron command
curl https://yoursite.com/wp-cron.php?doing_wp_cron=SECRET_KEYIP Whitelist: Restrict wp-cron.php access to server IP or external cron service IP.
Disable Public Access (.htaccess):
<Files wp-cron.php>
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
Allow from YOUR_SERVER_IP
</Files>Testing Cron Configuration
Verify cron works before relying on it:
Manual Trigger:
php /path/to/wp-cron.phpOr via browser:
https://yoursite.com/wp-cron.php?doing_wp_cron
Check Output: Should see blank page (success) or error messages.
Force Backup Creation: Use Backup Copilot Pro’s manual backup button to verify plugin works.
Wait for Scheduled Time: Monitor logs around scheduled backup time to confirm cron executes.
Email Notification Test: Configure backup completion emails, verify you receive them.
Troubleshooting Cron Failures
Common issues and solutions:
Cron Not Running: – Verify crontab entry exists: crontab -l – Check cron service running: systemctl status cron – Verify file paths in cron command – Check file permissions (wp-cron.php must be readable)
Backups Still Missing: – Verify WP-Cron actually disabled (check wp-config.php) – Confirm no caching preventing cron execution – Check memory and timeout limits – Review debug.log for errors
Partial Backups: – Increase execution time limit – Increase memory limit – Split backup into smaller pieces – Check for database locks
Multiple Failed Attempts: – Add lock mechanism to prevent overlapping – Increase WP_CRON_LOCK_TIMEOUT – Stagger backup schedules
Conclusion
Reliable WordPress cron is essential for scheduled backups. WP-Cron’s visitor-triggered nature makes it unsuitable for critical tasks on low-traffic or cached sites. Disabling WP-Cron and implementing server cron ensures backups run exactly when scheduled, regardless of site traffic.
Setup requires minimal effort—add one line to wp-config.php and configure one cron job—but delivers massive reliability improvements. Monitor cron execution through logs and notifications, optimize PHP settings for backup resource requirements, and prevent overlapping executions with proper locking.
External cron services provide alternative for shared hosting without cron access. Test configuration thoroughly and monitor continuously to ensure scheduled backups protect your WordPress site reliably every day.
External Links
- Understanding WP-Cron
- Disabling WP-Cron and Using System Cron
- Crontab Syntax Generator
- Debugging WordPress Cron
- cPanel Cron Jobs Documentation
Call to Action
Never miss a scheduled backup again! Backup Copilot Pro works perfectly with both WP-Cron and server cron. Reliable scheduling, email notifications when backups complete—protect your site 24/7!

