SpipCP
Sites

Scheduled tasks

WordPress runs scheduled work on a real system timer here, not on visitor page loads — so it fires on an empty site, never delays a request, and does not need the constant that makes backup plugins report a healthy site as broken.

WordPress's own scheduler has one structural flaw: it is driven by traffic. On a default install every page load checks whether something is due and, if so, fires a second request back at the site to run it. A site with no visitors runs nothing — a scheduled post stays unpublished, a backup never starts — and a site with visitors pays for the check on the request path.

A site here runs its schedule from a system timer instead. The timer fires on its own clock, whether or not anyone is looking, and no visitor ever waits for it.

Choosing the interval

Scheduled tasks on a site's WordPress tab sets how often the timer runs: every minute, every 5 minutes (the default), every 15 minutes, or hourly. Saving the setting rewrites the timer immediately — the change does not wait for a relaunch.

The interval is the resolution of the schedule, not a delay added to it. Work due at 09:02 under a 5-minute timer runs at 09:05. Shorter intervals suit a store or anything with queued jobs; hourly is enough for a brochure site whose only scheduled work is update checks.

The timer runs as the site, not as root

Scheduled work is a common way for a docroot's ownership to drift, because whatever the scheduler runs as is what ends up owning the files a plugin writes. The timer runs as the site's own runtime user — the same user its PHP runs as — so a backup plugin's output is owned by the site that has to read it back. See File ownership.

Why no plugin complains about it

This is the part that usually goes wrong on other hosts, and it is worth explaining because the symptom is loud.

The conventional way to take WordPress's scheduler off the request path is to define DISABLE_WP_CRON in wp-config.php. It works, and it has one flaw that is not technical: it is the only signal a plugin can read. A plugin cannot see a system timer, so every plugin that cares about scheduled work reads that constant as this site's schedule is broken and says so on screen —

In order to execute the scheduled backups properly, please set the DISABLE_WP_CRON constant to false.

The warning is a false alarm. A timer that fires every five minutes is strictly more reliable than one that fires only when a visitor happens to arrive. But it cannot be answered, because WordPress offers no way for a host to tell a plugin that a real scheduler exists — which is why essentially every managed host trips it, and why some of them publish support articles whose only purpose is explaining the warning away.

So the constant is not used. A must-use plugin removes the spawner's hook instead:

remove_action( 'init', 'wp_cron' );

That is the same behaviour reached from the other side. Core registers the spawner exactly once, and the function it defers to has no other caller, so removing that one action stops the page-load spawn completely — while no constant is defined for a plugin to misread. Backup and staging plugins see an ordinary site and say nothing, because as far as scheduled work is concerned the site is ordinary, and rather better served than most.

Where the truth is published instead

Silencing a warning without replacing it would leave a site whose scheduler is invisible: wp-config would read as though WordPress were still handling its own schedule.

So the same must-use plugin registers a Site Health test, under Tools → Site Health in WordPress. It reports that scheduled tasks are run by a system timer — and, more usefully, it measures whether they are actually being cleared rather than asserting that a timer was once configured:

  • Scheduled tasks are running — nothing is overdue, or what is due will run on the next tick.
  • Scheduled tasks are overdue — events are late by longer than any configured interval, which means the timer is not firing. Reported as critical.

A configuration check cannot tell a working timer from one that was installed and later stopped. This test can, and it is the site itself doing the reporting.

Keeping it that way

Both halves — the must-use plugin, and the absence of the constant — are written by the launch. Anything that relaunches the site re-applies them, and saving any setting on the WordPress tab is a relaunch, so the ordinary way to re-assert them is to press Save & apply. A WordPress core update, including an automatic one, cannot disturb them: core replaces its own files and never touches wp-content or wp-config.php.

What can disturb them is a tree that arrives from somewhere else. A restore from a backup taken before this existed, a migration, or re-adopting a site brings wp-config.php and wp-content out of an archive — plugin absent, constant back — onto a site that serves perfectly and passes its health check. Two things catch that:

  • A restore ends in a relaunch, so a restored site is put back on the current contract as part of restoring it. See Restore and clone.
  • Settings reach grades the contract as one of its tiers, reporting plugin present, no DISABLE_WP_CRON against what the docroot actually holds — and repairs it through the same Apply. It is checked for the whole fleet whenever the panel's build changes, so a site that slipped is found without anyone thinking to look. See Upload limits.

If a plugin still asks for the constant

A small number of plugins check for DISABLE_WP_CRON being defined as false, rather than checking whether it is truthy. Nothing is wrong with the site: the schedule is running on the timer, and Site Health will say so. Dismissing the notice is correct.

Next steps

On this page