Skip to main content

Why isn't Drupal cron running as often as it should?

Has it happened to you that you set up a Drupal site for a client and after launch, they complain because important things aren't happening?

  • Search is not returning all the new results that have been created.
  • Backups aren't running.
  • Caches are not being cleared. You keep seeing content in its old versions ...
  • Logs are not emptied when it is time.
  • Among other inconveniences...

All of these things should run automatically when you run cron (Drupal comes with the ability to run cron automatically) at specific intervals, like every 3 hours. So when does cron run, if not at the specified interval?

Setting cron to run every 3 hours does not necessarily mean that cron will run every 3 hours. This is because it is not automatic. Something needs to trigger cron to run. This trigger occurs when a user visits the site. As part of processing the page request, Drupal will last check to see if cron has been run and will run cron as part of the request if it is time to do so. If cron is set to run every three hours and it has been three hours since it last ran, it will run as part of the page request for the user who arrives at the page at that time.

But what if you have an extremely low-traffic Drupal site, application, or intranet? If no one visits the site, cron will not run. Or if one user visits the site and cron runs, and another user visits the site 2 hours and 59 minutes later, cron will not run because three hours have not yet passed. If a third visitor visits 3 hours later, cron will run. But that's almost 6 hours since the previous cron run.

This works well for small sites, with few content changes and few important cron tasks. The problem is that most Drupal sites are some kind of web application with very dynamic content or cron intensive tasks.

It is not the same as a personal blog like this web you are reading right now, then e-commerce where there are daily product imports, or an intranet connected with an external api that sends data periodically, or a web that has an advanced search engine where data has to be indexed in ElasticSearch or Solr for example.

And as I have already said, you are depending on your site having enough users during all hours of the day to ensure that the cron will run every few hours.

What about sites with enough traffic?

So, on sites with low traffic, relying on cron to run automatically is problematic because the time cron runs will be erratic. What about sites that get more traffic? They should get enough traffic for cron to run more or less on time. But they will face another problem: the time cron takes to run. Because cron runs as part of a page request for a real user, it can slow down the page for that user.

Solution: don't rely on automatic cron runs.

The solution is to not rely on automatic cron runs. Instead, you can set it up on the server as a cron job. This doesn't rely on page requests, so it will always run on time. And it will run in the background, so it won't slow down page requests for users.

This is the best solution, and it's how cron tasks have been recommended to use in Drupal for years.

The problem is that not all cheap shared hostings allow you to set up cron tasks.

There are 2 ways to set up cron on a server:

  1. The server has a control panel like Cpanel or a custom panel made by the hosting company. You just have to enter that control panel and configure the cron tasks. Normally in the cron job you specify the Drupal URL to make a CURL call to the URL that runs the CRON.
  2. The server does not have a control panel because it is a dedicated server. You have to ask the people who manage the server, who have to set up a cron job. On a dedicated server there are two ways to make a call to the Drupal cron:
  • Use a call to DRUSH to execute the cron call.
  • Make a CURL to the Drupal cron URL (same case as on shared hosting).

I recommend using the DRUSH execution of the cron whenever possible. This is because this way we skip the typical limitations of running calls to php URLs (execution time limit, memory limit, ...). This is very noticeable when the cron is in charge of performing periodic imports of content to update some pages of the web.

Disable Drupal's automatic cron

Now that you have it running at the server level, you can disable Drupal from running the cron. Simply change the cron setting "Run Cron every" to never/never.

Another recommended option is to disable the Drupal module.

And why do I want to disable the "automatic cron"? Well, as I said before, for web performance.

Although you are running the cron at the server level ... if before it runs from the server, a user arrives at your website ... then the cron will run on the loading of the page that is looking at that user. And this implies that the loading of that page will be much slower than normal for that particular user.

Verify that cron is running.

Wait until the cron runs. Then go back to the cron configuration page. If it has run correctly, you will see that the "Last run" has been updated and shows how long ago the cron was run.

And that's it! Cron will now run in the background according to the specified time frames, regardless of the amount of traffic your site receives. And as your site grows and gets more traffic, you don't need to worry about cron slowing down page requests.