
If your WordPress site feels sluggish or your server CPU spikes unexpectedly, WP-Cron may be the culprit. WordPress ships with its own pseudo-cron system — wp-cron.php — that runs scheduled tasks (backups, email, update checks) by triggering on every page load. On busy sites, this means hundreds of extra PHP processes every hour. The fix is straightforward: disable WP-Cron and replace it with a real server cron job.
The core problem: WP-Cron doesn't run on a schedule — it runs on every HTTP request. A site receiving 1,000 visits/hour potentially triggers wp-cron.php 1,000 times per hour, even if scheduled tasks only need to run once.
Step 1: Disable WP-Cron in wp-config.php
Open your wp-config.php file (in the WordPress root directory) and add this line before the /* That's all, stop editing! */ comment:
define('DISABLE_WP_CRON', true);
This prevents WordPress from spawning its internal cron on every page load. Scheduled events will not run until you set up the real cron job in Step 2.
Do not skip Step 2. After disabling WP-Cron, WordPress will not run any scheduled tasks until a real cron job is configured. Backups, update notifications, and scheduled posts will all stop working temporarily.
Step 2: Set Up a Real Cron Job on DirectAdmin
- Log in to DirectAdmin → Advanced Features → Cron Jobs
- Set the schedule to run every 5 minutes (recommended) or every 1 minute for high-traffic sites
- Enter this command:
wget -q -O /dev/null "https://yourdomain.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1
Or use curl if wget is not available:
curl -s "https://yourdomain.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1
Replace yourdomain.com with your actual domain. The >/dev/null 2>&1 part suppresses all output so you don't get cron emails every 5 minutes.
Crontab Schedule Reference
| Cron Expression | Meaning |
|---|---|
| */1 * * * * | Every 1 minute |
| */5 * * * * | Every 5 minutes (recommended) |
| 0 * * * * | Every hour, on the hour |
| 0 0 * * * | Daily at midnight |
Step 3: Verify with WP Crontrol Plugin
WP Crontrol (free on WordPress.org) lets you view, edit, delete, and manually run all cron events in WordPress. After setting up the server cron job:
- Install WP Crontrol from Plugins → Add New
- Go to Tools → Cron Events
- Check the "Next Run" time for events — they should update correctly after your server cron fires
- You can also add or remove custom cron events from this screen
Understanding Cron Expressions Before You Configure
Whether you use DirectAdmin's cron job UI or a raw crontab, you need to understand cron expression syntax. A cron expression has five fields: Minute, Hour, Day of Month, Month, and Day of Week. Each field accepts a number, an asterisk (every), or a step value like */5 (every 5).
| Expression | Meaning | Best for |
|---|---|---|
*/5 * * * * | Every 5 minutes | Most WordPress sites (recommended) |
*/1 * * * * | Every 1 minute | High-traffic sites needing precision |
0 * * * * | Every hour on the hour | Very low-traffic sites |
0 2 * * * | Daily at 2:00 AM | Daily backup jobs |
0 0 * * 0 | Every Sunday at midnight | Weekly maintenance tasks |
Not sure if your expression is correct? Use AsiaGB's free Cron Expression Generator to build and validate expressions without memorizing the syntax.
Common Problems After Disabling WP-Cron
After disabling WP-Cron and setting up a server cron job, you may encounter these issues if something is misconfigured:
Scheduled Posts Are Not Publishing
Cause: the server cron job is not running because the PHP binary path is wrong. Verify the correct path with which php via SSH. Some servers require php8.1 or php8.2 instead of just php.
# Find the correct PHP path
which php
# or check alternatives
ls /usr/bin/php*
Cron Emails Flooding Your Inbox
Add > /dev/null 2>&1 at the end of your cron command to discard all output, or set MAILTO="" as the first line of your crontab to suppress all emails globally:
MAILTO=""
*/5 * * * * php /home/username/domains/example.com/public_html/wp-cron.php > /dev/null 2>&1
Backup Plugin Is Not Running on Schedule
Plugins like UpdraftPlus and BackWPup rely on WordPress Cron to trigger their own scheduled backups. With a real server cron running wp-cron.php every 5 minutes, those plugin tasks will fire at their configured times — no additional configuration needed. The server cron simply ensures the WordPress cron queue is processed reliably.
Pro tip: Schedule heavy backup jobs between 1:00 AM and 4:00 AM when traffic is lowest. This keeps CPU usage predictable and ensures backups complete without competing with live visitor requests.
WP-Cron on WordPress Multisite Networks
On a WordPress Multisite installation, disabling WP-Cron works the same way but with one key difference: you only need to make one change and set up one cron job regardless of how many sub-sites you have.
- Add
define('DISABLE_WP_CRON', true);to the mainwp-config.php— this applies to all sub-sites in the network automatically - Set up one server cron job pointing to the main site's
wp-cron.php— WordPress processes the cron queue for all sub-sites from there - If sub-sites use domain mapping (separate domains), ensure
wp-cron.phpis accessible via the primary domain - Use WP Crontrol under Network Admin to view and manage cron events across all sub-sites from a single screen
Before vs After: Performance Impact
| Aspect | WP-Cron (default) | Server Cron |
|---|---|---|
| Trigger | Every page load | Every 5 minutes exactly |
| Page load impact | Adds PHP overhead to all requests | Zero impact on page loads |
| Reliability | Requires visitors to trigger | Runs even with no traffic |
| CPU usage | High on busy sites | Predictable, low overhead |
Securing wp-cron.php After Disabling WP-Cron
Once you switch to a server cron job, the file wp-cron.php is still publicly accessible via HTTP. This exposes a potential attack vector: anyone can send HTTP requests to trigger your cron queue or attempt a denial-of-service attack by flooding it with requests. The solution is to block public access to the file while keeping the server-side cron job working.
Block Access on Apache (.htaccess)
Add these lines to the .htaccess file in your WordPress root directory:
# Block public access to wp-cron.php
<Files wp-cron.php>
Order allow,deny
Deny from all
Allow from 127.0.0.1
</Files>
This allows only localhost (127.0.0.1) to access wp-cron.php, which is sufficient when the cron job runs via PHP CLI rather than HTTP.
Block Access on Nginx
# Inside your Nginx server block
location = /wp-cron.php {
allow 127.0.0.1;
deny all;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Note: If you use curl or wget in your cron command instead of PHP CLI, update the cron command to call localhost directly: curl -s http://127.0.0.1/wp-cron.php?doing_wp_cron -H "Host: yourdomain.com" — this avoids triggering your own firewall block.
Using WP-CLI for Cron Jobs
If your hosting supports WP-CLI (WordPress Command Line Interface), it offers a more powerful alternative to running wp-cron.php directly. The command wp cron event run --due-now processes only events that are actually due, with better error visibility:
# WP-CLI cron command (replace php path with WP-CLI runner)
*/5 * * * * /usr/local/bin/wp cron event run --due-now \
--path=/home/username/domains/example.com/public_html \
--quiet > /dev/null 2>&1
| Method | Advantages | Limitations |
|---|---|---|
| PHP CLI (wp-cron.php) | Works on any hosting, simple setup | Must use correct PHP binary path |
| WP-CLI | Detailed logs, easy to debug | Requires WP-CLI installed on server |
| curl / wget (HTTP) | No shell access needed | HTTP overhead, IP must be allowed |
Troubleshooting Cron Jobs That Are Not Running
If you have set up a server cron job but WordPress tasks still aren't running on schedule, check the cron daemon log first — most failures stem from an incorrect PHP path, insufficient file permissions, or a missing environment variable.
# Check cron logs on CentOS / AlmaLinux
tail -50 /var/log/cron
# Check cron logs on Ubuntu / Debian
grep CRON /var/log/syslog | tail -50
# Test your cron command manually in shell
php /home/username/domains/example.com/public_html/wp-cron.php
echo $? # Should return 0 (success)
If the command works in a terminal session but fails silently in a cron job, the cause is almost always the PATH environment variable — the cron environment has a much narrower PATH than your interactive shell. Fix this by specifying absolute paths for all binaries:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/5 * * * * /usr/bin/php8.2 /home/username/domains/example.com/public_html/wp-cron.php > /dev/null 2>&1
Long-Term Maintenance: What to Check After Migration
After switching from WP-Cron to a real server cron job, add these checks to your site maintenance routine to ensure everything remains healthy over time:
- Check WP Crontrol monthly to confirm "Next Run" times are updating correctly and no events are stuck in the queue
- After each WordPress or major plugin update, verify that no plugin has re-enabled WP-Cron by checking
wp-config.phpforDISABLE_WP_CRON - Monitor server CPU usage around cron run times — a sudden spike may indicate a heavy task that needs its own dedicated cron schedule
- If you migrate to a new hosting plan or server, re-create the cron job in DirectAdmin before going live — it does not transfer automatically
- Review your cron logs periodically; a cron job that fails silently for weeks can cause backup plugins to miss their scheduled run without any visible warning
Final verification: Wait 10–15 minutes after setup, then open WP Crontrol (Tools → Cron Events). If the "Next Run" timestamps for all events are updating correctly relative to your schedule, the server cron job is working perfectly.
WordPress Hosting with DirectAdmin Cron Job Support
AsiaGB Hosting includes DirectAdmin with full cron job management. Set up server-side cron jobs without command-line access. Starting at 500 THB/year.
View Hosting Plans →