Drupal's built-in cron piggybacks on page visits, just like WordPress and Nextcloud. This guide covers what it actually runs, how to switch to a proper external trigger, and how to monitor it with Cloud Cron.
Drupal ships with "automated cron" turned on by default. Every three hours or so, when someone visits the site, Drupal checks if it's time to run background tasks and tacks the work onto that page request. If nobody visits, nothing runs. If the site gets traffic but cron tasks are heavy, the visitor who triggers it gets a slower page load.
Drupal's own documentation recommends external cron over the built-in system. The reasoning is simple: it always runs on schedule, and it doesn't add processing overhead to user requests. Yet most Drupal sites still run on automated cron because switching to external requires either SSH access or a third-party service, and most site owners never get around to it.
What Drupal runs through cron
Drupal core and contributed modules register tasks that fire on every cron run. The list grows with every module you enable.
Search indexing. Drupal indexes content for its built-in search in batches during cron. Without regular runs, new pages and updated content don't appear in search results. On a site with frequent content changes, a three-hour cron gap means search is always lagging behind what's actually published.
Cache and cleanup. Expired cache entries, old session data, temporary files, and aggregated CSS/JS that's no longer referenced all get cleaned up by cron. Skip too many runs and the database tables bloat, the tmp directory fills up, and performance degrades.
Content publishing. Scheduled content (nodes set to publish at a future date) relies on cron to actually go live. If cron doesn't run, a blog post scheduled for 9 AM sits in draft until the next cron trigger, whenever that happens to be.
Contributed modules. Commerce processes abandoned carts and sends order notification emails. Webform cleans up submissions. Feeds module pulls in RSS and external data. Redirect module purges 404 logs. Backup and Migrate runs scheduled database dumps. Each module adds its own cron hook, and they all wait in line for the next run.
Update checks. Drupal checks for available module and core updates during cron. Without it, you won't see security advisories in the admin status report until someone manually triggers a check.
You can see when cron last ran under Administration > Reports > Status report. If the timestamp is hours old on a site that should be running every few minutes, something is off.
Signs your Drupal cron is stuck
- Search results outdated. New or updated content doesn't appear in search until someone manually runs cron.
- Scheduled posts not publishing. Content set to go live at a specific time stays in draft past its publish date.
- Database tables growing. Expired sessions, old cache entries, and temp files pile up because cleanup never runs.
Setting up external cron for Drupal
Drupal provides a unique cron URL that triggers all registered tasks when called. Find it at Administration > Configuration > System > Cron. The URL looks like this:
https://yoursite.com/cron/CRON-KEY-HERE
The cron key is a random token that prevents unauthorized triggering. Anyone with the URL can run your cron, so treat it like a password.
Before setting up external cron, disable the built-in automated cron. Go to Administration > Configuration > System > Cron and set "Run cron every" to "Never." Otherwise both systems will fire, and you might hit overlapping runs.
Via SSH (Drush or wget)
If you have terminal access, Drush is the cleanest option:
*/15 * * * * cd /var/www/drupal && vendor/bin/drush cron
Drush runs cron through PHP CLI, avoiding web server overhead and timeout limits. If Drush isn't installed, use wget or curl to hit the cron URL:
*/15 * * * * wget -O /dev/null -q "https://yoursite.com/cron/CRON-KEY-HERE"
Via hosting panel (cPanel, Plesk)
Paste the wget or curl command into your hosting panel's cron scheduler. cPanel has it under "Cron Jobs," Plesk under "Scheduled Tasks." Set it to every 15 minutes for most sites, or more frequently if you rely on search indexing or scheduled publishing.
Via external cron service
An external cron service calls your Drupal cron URL on schedule from outside the server. No SSH, no hosting panel dependency. The same approach that WooCommerce, PrestaShop, Nextcloud, and WHMCS use for their background tasks.
Common Drupal cron problems
Drupal cron looks simple, but a few issues show up repeatedly in support forums.
Cron semaphore lock. Drupal uses a semaphore to prevent overlapping runs. If a cron run crashes or times out midway, the lock stays set and blocks all future runs. The status report shows "Attempting to re-run cron while it is already running." Fix it by clearing the cron_last entry in the database or running drush sqlq "DELETE FROM semaphore WHERE name = 'cron'".
Timeout on heavy sites. Drupal's default cron timeout is 240 seconds. On sites with large databases, heavy search indexing, or dozens of contributed modules, cron can exceed this limit and get killed. The tasks don't complete, and Drupal logs a timeout error. Reduce the per-run workload by lowering the search index batch size (under Configuration > Search) and letting cron run more frequently so each run processes less.
Automated cron adding load to page requests. This is the built-in system's core weakness. When automated cron fires, it runs as part of a page request. A visitor loading the homepage gets a 5-second response instead of 200ms because cron decided to index 500 nodes. Disabling automated cron and using an external trigger solves this completely.
Wrong PHP version or path. Same issue that hits WHMCS and Nextcloud: the CLI PHP binary doesn't match the web server PHP. Drush needs the right PHP version, and crontab might point to an old one. Use the full path: /usr/bin/php8.2 instead of just php.
For sites using the Ultimate Cron module (which gives per-task scheduling), external cron should fire every minute so the module can manage individual task timing. Without frequent triggers, tasks show as "behind schedule" in the admin UI.
Monitor Drupal cron with WatchCron Cloud Cron
Drupal's status report page shows when cron last ran. Useful if you check it. Most site owners look at that page during initial setup and never again until something is visibly broken.
Cloud Cron replaces the built-in automated cron with a reliable external trigger and adds monitoring on top. You paste your Drupal cron URL, choose a schedule, and Cloud Cron calls it on time, every time. No SSH, no crontab to manage, no visitor dependency.
Cloud Cron supports flexible scheduling through standard cron expressions or preset intervals: every 5 minutes, every 15 minutes, hourly, or any custom pattern. For sites using Ultimate Cron, set it to every minute so the module can manage per-task timing internally.
Every call gets tracked. You see the full run history with HTTP status codes, response times, and timestamps. If the cron URL returns an error, times out (common on heavy sites), or becomes unreachable, WatchCron sends an alert through Slack, Telegram, email, or any of 20+ notification channels. A configurable grace period prevents false alarms from a single slow response while still catching real failures.
Why Cloud Cron works for Drupal
No more piggybacking on visitor requests. Cloud Cron triggers cron independently, on a fixed schedule
Every cron call logged with status code, response time, and timestamp. Catch timeouts and errors as they happen
Set Cloud Cron to fire every minute, let Ultimate Cron handle per-task scheduling internally
Managed hosting, shared hosting, Pantheon, Acquia, Platform.sh. If the cron URL is reachable, Cloud Cron works
For sites running Drush cron via server crontab, heartbeat monitoring adds a safety net without changing the trigger:
*/15 * * * * cd /var/www/drupal && vendor/bin/drush cron && curl -fsS https://ping.watchcron.com/your-monitor-id > /dev/null
If Drush fails or the server goes offline, the ping doesn't fire and WatchCron alerts you. Your existing setup stays the same. One curl call appended to the command is the only change.
Drupal's automated cron was designed for simplicity, not reliability. It works until it doesn't, and when it stops, you find out from broken search results or a scheduled post that never went live. WooCommerce, Magento, PrestaShop, and WHMCS all have the same pattern: a CMS that depends on cron but doesn't tell you when it breaks.
Cloud Cron triggers your Drupal cron on time and alerts you when something breaks. Free plan includes 3 Cloud Cron monitors.