WordPress: Block WP Cron on specific pages

Bastiaan Dewaele
4 min readAug 10, 2021

--

An photo by Sigmund on Unsplash that resamples the complexity with WP Cron

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.

FIle: wp-includes/cron.php

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

Other handy WordPress articles:

--

--

Bastiaan Dewaele
Bastiaan Dewaele

Written by Bastiaan Dewaele

Senior back-end developer in Ghent who likes writing sometimes weird / creative solutions to a specific problem.

No responses yet