If you have ever wondered how WordPress sends you email notifications, checks for plugin updates, or publishes scheduled posts automatically, the answer is wp-cron.php. It is one of those parts of WordPress that quietly does its job in the background, but understanding it, and knowing when to replace it, can meaningfully improve your site’s reliability and security.
What Is wp-cron.php?
wp-cron.php is WordPress’s built-in task scheduler. It handles all recurring and time-based tasks, including:
- Publishing scheduled posts at the exact time you set
- Sending email digests and notifications
- Checking for WordPress core, plugin, and theme updates
- Running backup plugin jobs
- Clearing transient cache
- Sending WooCommerce order emails
- Any custom scheduled task registered by a plugin or theme
It is, in short, the heartbeat of your WordPress site’s automation.
How Does It Actually Work?
This is where WordPress WP-Cron differs from what most people expect. Unlike a traditional server cron job that runs on a fixed schedule regardless of anything else, WP-Cron is triggered by page visits.
Here is what happens on every page load:
- A visitor (or a bot, or a search engine) loads any page on your site
- WordPress checks whether any scheduled tasks are due
- If yes, it spawns a background HTTP request to wp-cron.php to run those tasks
- wp-cron.php executes the due tasks and marks them complete
This design is clever for a shared hosting environment where you have no control over server-level cron. But it has real limitations.
The Problems with Default WP-Cron
Tasks only run when someone visits the site
If your site has low traffic, especially overnight or on weekends, scheduled tasks might not run on time. A post scheduled for 3:00 AM might not actually publish until the first visitor shows up at 9:00 AM. Same goes for backups, cleanup tasks, and update checks.
It can run too often on high-traffic sites
On the opposite end, if you have a high-traffic site, WP-Cron gets triggered on every single page load. Most of the time there is nothing to run, but the overhead of checking adds up. On busy sites this can contribute to slower response times.
It can be triggered externally
wp-cron.php is a publicly accessible PHP file. Anyone who knows the URL (and every security scanner does) can send repeated GET requests to it, forcing WordPress to run its scheduled task check over and over. This is a low-severity issue, but it is unnecessary exposure.
It can cause duplicate task execution
On sites with heavy traffic and poorly written plugins, WP-Cron can occasionally fire the same task multiple times simultaneously, leading to duplicate emails, double backups, or race conditions in custom code.
When Should You Disable It?
Disabling the default WP-Cron and replacing it with a real server cron job makes sense in these situations:
You have a low-traffic site
If your site does not get consistent traffic at all hours, scheduled tasks will be unreliable. A server cron job runs on a fixed schedule regardless of traffic, so your 3:00 AM backup actually runs at 3:00 AM.
You have a high-traffic site
Ironically, the fix is the same. On a busy site, you want WP-Cron to stop being triggered on every page load. A server cron running every 5 or 15 minutes is far more efficient.
You need precise scheduling
If you publish content on a tight editorial schedule, run time-sensitive WooCommerce promotions, or have plugins that depend on exact timing, visitor-triggered cron is not reliable enough.
You want to reduce attack surface
Disabling the default cron removes public access to wp-cron.php entirely. Less exposure is always better.
When Is It Fine to Leave It As Is?
Not every site needs to change anything. Default WP-Cron works well enough if:
- You are on shared hosting with no SSH or cron access
- Your site has steady, consistent traffic throughout the day
- You do not rely on precise scheduling for anything critical
- You are running a simple blog or brochure site without WooCommerce or complex plugins
In these cases, the default setup is acceptable. The risk is low and the effort of changing it may not be worth it.
What Stops Working When You Disable WP-Cron
This is the part most guides skip over. When you add DISABLE_WP_CRON to wp-config.php without setting up a replacement, scheduled tasks simply stop running. Here is what that means in practice:
- Scheduled posts will not publish. Posts you set to go live at a specific time will sit in “Scheduled” status indefinitely until a cron job processes them.
- Backup plugins stop running. UpdraftPlus, BackupBuddy, and similar plugins rely entirely on WP-Cron. No cron means no automatic backups.
- WordPress will not check for updates. You will need to manually check for core, plugin, and theme updates in the dashboard.
- WooCommerce automation breaks. Order status transitions, subscription renewals, abandoned cart emails, and many other WooCommerce automated actions depend on WP-Cron.
- Email notifications may stop. Plugins that send digest emails, activity summaries, or scheduled reports will go silent.
- Membership and subscription plugins break. Expiry checks, renewal reminders, and account status updates will not happen.
- Cache clearing schedules stop. Plugins that clear or warm caches on a schedule will stop doing so.
The takeaway: disabling WP-Cron without a replacement does not just reduce one feature. It can silently break a large part of your site’s automated functionality. Always set up a server cron job before or immediately after disabling the built-in one.
How to Disable WP-Cron and Set Up a Real Server Cron
Step 1: Disable the built-in WP-Cron
Open your wp-config.php file and add this line before the /* That's all, stop editing! */ comment:
define('DISABLE_WP_CRON', true);This stops WordPress from spawning the background HTTP request on every page load. Your scheduled tasks will no longer run automatically, until you set up the server cron in the next step.
Step 2: Create a server cron job
If you have SSH access to your server, run:
crontab -eThen add one of these lines, depending on how often you want tasks to run:
Every 5 minutes (recommended for WooCommerce or time-sensitive sites):
*/5 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1Every 15 minutes (recommended for most sites):
*/15 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1Replace yoursite.com with your actual domain. The doing_wp_cron parameter tells WordPress this is a legitimate cron call and prevents it from spawning additional background requests.
Alternatively, using PHP CLI directly (faster and more reliable):
*/15 * * * * php /var/www/html/wp-cron.php > /dev/null 2>&1Replace the path with the actual path to your WordPress installation.
Step 3: Verify it is working
Install the free WP Crontrol plugin. It lets you see all scheduled events, when they last ran, and when they are next due. After setting up your server cron, you should see tasks running on schedule.
What About Managed Hosting?
If you are on a managed WordPress host like WP Engine, Kinsta, or Flywheel, they often handle this for you automatically. Check your hosting panel or documentation. Some hosts disable WP-Cron and run their own cron integration by default.
What Happens to the wp-cron.php File Itself?
Disabling WP-Cron with DISABLE_WP_CRON does not delete or block the file. wp-cron.php is still publicly accessible. If you want to block direct external access entirely while still allowing your server cron to call it, you can add this to your .htaccess file:
# Block external access to wp-cron.php
<Files "wp-cron.php">
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Files>This allows only local server requests (which your cron job uses) while blocking all external access. If your server cron uses wget with the full URL, you may need to allow the server’s own IP instead of 127.0.0.1.
Summary
WP-Cron is a clever solution to a real problem, but it is a workaround, not a proper scheduler. For any site where timing matters, traffic is unpredictable, or performance is a priority, switching to a real server cron job is the right call. For simple sites on shared hosting where none of that applies, the default setup is fine.
The key points to remember: WP-Cron runs on page visits, not on a real clock. Disabling it requires you to set up an alternative. And leaving it enabled exposes wp-cron.php to direct external requests, which is a minor but unnecessary risk.
Need Help?
If you are not sure how to configure server cron on your hosting environment, or if you want someone to review your WordPress scheduled tasks setup, get in touch with our team.