WordPress: Block WP Cron on specific pages
WordPress Cron is something that handles time-based tasks and automatic updates. Now in this article, I’ll explain to you how to programmatically disable WP Cron in certain pages / REST routes. Without affecting other pages.
Drawback of WP Cron
Now one of the major drawbacks you may encounter, is that WP Cron is silently running in the background. By default, WordPress handles these time-based tasks on every page load.
- Looking for new updates
- Running a daily task
With smaller websites that have a low traffic, you’ll probably never encounter problems.
Large and complex websites
But once you’re dealing with larger websites, that have a lot of traffic but also rely on web-hooks or something time-consuming.
And like mentioned before, WordPress performs WP Cron by default on every page load and WP-JSON endpoints.
Scenarios
I have heard of customers or developers who complained they had failed web-hooks.
- The user visits a page and would time-out because an update is running in the background
- Stripe sends to our web-hook inside WordPress, but because of a background task that takes too long. the web-hook never returns a response back-on-time or
- A cron-job is migrating data vice-versa from Salesforce to WordPress
All these examples could be triggered on page load and could’ve resulted in a white page for users that are interested in your product.
Other problems with WP Cron
But there are also other common issues.
- WP Cron consumes CPU usage on every page-load
- It generally slows down every page, if your website contains a lot of background tasks and it can be an open invite for DDoS-attacks
General solution
Now there is a simple solution to solving this problem, just by adding peace of code in wp-config file.
<?php
// wp-config.php define('DISABLE_WP_CRON', true);
But it does enable auto-updates and all of the cron-jobs. So if you still need cron-jobs, you can always manually enable them with cron-tab in Linux.
General tips
- Only run cron-jobs every few hours
- Run heavy tasks during midnight; updates
Alternate solution for plugin developers
Let’s say you’re a plugin developer, that integrates a web-hook and a person who downloaded has no coding-skills, or are just not technical enough.
- You’ve developed a third-party plugin
- Users are installing your plugin
- They are encountering the mentioned problem
- The person that uses your plugin doesn’t have any programming skills
This kind of behavior of WordPress can result in frustration, and sometimes plugin consumers will easily blame it on the plugin developers.
Below is an example of how to create a REST-route, that results in a path /wp-json/webhook.
// response:
// {
// "data": {
// "success": true,
// "id": "123"
// }
// }
add_action('rest_api_init', function() {
register_rest_route('foo', 'webhook', array(
'methods' => 'POST',
'callback' => 'handle_foo_webhook',
'permission_callback' => '__return_true',
));
});
Disable cron-jobs for your own plugin
The following code helps to disable WP Cron programmatically, but without interfering with other pages.
In our solution we’re using plugins_loaded, this is a useful hook for disabling certain functionality like auto-updates or cron-jobs.
The plugins_loaded action hook fires early, and precedes the setup_theme, after_setup_theme, init and wp_loaded action hooks.
function custom_disable_cron() {
if (
isset($_SERVER['REQUEST_URI']) &&
strpos($_SERVER['REQUEST_URI'], '/wp-json/foo/') !== false
) {
// Disable WP Cron, this could also be applied
// for membership pages if (!defined('DISABLE_WP_CRON')) {
// Fully disable WP Cron
define('DISABLE_WP_CRON', true);
} // When the constant already exists
remove_action('init', 'wp_cron');
remove_action('wp_loaded', '_wp_cron');
}
}
add_action('plugins_loaded', 'custom_disable_cron', 0, 20);
We are programmatically doing the following:
- We are adding an action hook, that is fired after all plugins have been loaded
- We watching every request that matches our foo namespace
- Disabling auto-updates and cron-jobs by defining the constant
- We are removing two action hooks, to prevent cron-jobs from running as a last measure
I found this solution, by inspecting the source code and removing the mentioned action hooks.
Generally, if you want to disable Core features, you just set a constant or start removing hooks that you encounter of the source-code of WordPress ;)
Short answers
Here are some short opinions that may be important.
- Should you keep WP Cron enabled: Yes, it is important to keep websites up-to-date with the latest security updates. You can always run wp-cron.php with a cron-tab in the late evening
- Should you disable WP Cron on every page: Yes, you should disable it and instead use wp-cron.php. This will increase performance and reduce CPU-usage on ever page