The nightmare that is wp-cron.php
One major gripe I have with WordPress is the default wp-cron.php implementation. If you are familiar with how WordPress uses wp-cron.php by default, you may want to skip ahead to the next section of this article.
What is wp-cron.php & How does it work?
The file wp-cron.php is the portion of WordPress that handles scheduled events within a WordPress site. Anything that has to do with scheduling posts or publications and really anything date/time oriented is governed by the wp-cron.php file.
In order for wp-cron.php to work properly, it needs to be executed frequently, but no more than once per minute. However, the default behavior does not require you to set up a real system level cron job on your server. Instead, it uses a piggyback method on every incoming request. When a request comes into the site, WordPress will generate an additional request from itself to the wp-cron.php file over HTTP(S). That sounds pretty innocuous, right?
Why is the default wp-cron.php behavior a nightmare?
The default method works perfectly fine on a small site with very few visitors per hour. However, when implemented on a medium or larger site or even a site that is being scanned by bots (which is very common these days), this means you get twice fold whatever traffic you are currently handling. It becomes a rudimentary DDoS attack against yourself. This is because the cron is being executed multiple times a minute using an HTTP request. The HTTP request generates additional overhead by having to generate, negotiate and establish the connection over a network socket. It even impacts the effective capacity of your underlying web server. This solution does not fare well in most situations, and honestly, it should be removed as the default behavior due to its propensity to be abused or turned into an attack vector on a server just from regular traffic.
Well, what are the alternatives?
The only real alternative and the much better solution is to configure a regular system cronjob that executes the wp-cron.php script directly through PHP every minute. This ensures that any scheduled tasks are indeed executed at their scheduled time. It also should not be done via an HTTP request but a direct execution of PHP to avoid hindering the web server’s capacity or generating additional memory overhead on the network layer.
How do I disable the default wp-cron.php behavior?
This is pretty universal and simple to do. You need to update your wp-cronfig.php file to include the following setting:
define('DISABLE_WP_CRON', true);
- You can typically find your wp-config.php file in your site’s public_html directory.
- This new setting should be put in the file just after the DB_COLLATE database line which looks like the following
define('DB_COLLATE', '');
How do I set up a system cron job?
This is simple in cPanel, assuming your hosting provider has enabled the cron job feature on your account. The cPanel Cron Jobs Documentation goes into greater details but essentially you do:
- Login to cPanel for your domain: yourdomain.tld/cpanel
- Input “cron” in the quick search box near the top of the page.
- Click “Cron Jobs” icon that appears.
- If it does not appear, your account does not have the Cron Jobs feature enabled and you will need to talk to your hosting provider for help setting up the cron or switching to a package that includes the Cron Jobs feature.
- Pay attention to the Cron Jobs page, it will provide you the exact location of your PHP binary. You will need to copy that path into the command box at the bottom of the page and alter the file being executed by PHP to be your /home/username/public_html/wp-cron.php file instead. Using the full path.
- Select the first entry (“*”) for each parameter. This will execute the wp-cron.php file every minute.
- Click that add cron button and you’re done.
Why are you so harsh on this practice, it seems reasonable and easy to fix?
I believe it is up to the software engineers that develop our digital world to impress upon themselves a sense of responsibility for their products. WordPress is ubiquitous these days and with auto installer software, like Softaculous, WordPress gets installed on a very large majority of sites. They are installed with the default behavior enabled, which is essentially an attack vector on any server. Now with the hosting industry being so prevalent in our lives, many people have WordPress sites and do not know about this issue until it cripples their site. The default integration is sorely inadequate and should be removed. Today on one server alone, I found over 500 different installs of WordPress and watched as a bot hit each site on the server. Every one of those sites suddenly became a liability for the server’s stability.
I realize that this problem is handled on a case by case basis. However, with so many installs around the world, it would be better addressed by WordPress rather than every single hosting provider who has to set up special conditions on their server to protect against the hole this software generates. The cost of removing this behavior and forcing site owners to generate a system cron should be baseline and a notice placed within the WordPress admin interface that scheduled tasks will not be executed until a system cron job is created properly. This is within my programming skills, so I know it’s well within theirs.
WordPress aims for ease of use, so their target consumers are those that typically know little about hosting caveats. I believe the responsibility here lies entirely with WordPress to fix and they have taken the stance against it. In the meantime, the System Admins in the hosting industry have to suffer through this terrible “feature” when examining servers that have fallen out of control due to a bot running over a default WordPress install.