WordPress Cron on Every Page Load

We rate this tip B tier: turn off WordPress's page-load cron with one line in wp-config.php and let the server's own cron call it on a schedule. George Vanous's host counted 27,272 requests for wp-cron.php in his logs, and his notes add a trap of their own, a plugin's cron script that only runs from crontab after a cd into its folder.

We rate this tip B tier: it is one line and one crontab entry, WordPress's own handbook still recommends it, and it will not change your life unless your site is busy. The Plugin Handbook's cron chapter says WP-Cron looks at its list of scheduled tasks on every page load, and its page on the system task scheduler (last modified Mar 20, 2025, read Nov 10, 2026) gives the fix: define( 'DISABLE_WP_CRON', true ); plus a scheduled request for wp-cron.php. George Vanous's host counted 27,272 requests for that file in his access logs. We think the more useful half of his note is the part no handbook has: why a plugin's cron script that works when you test it by hand can fail every hour from crontab.

We think the WordPress release that is current in Sep 2027 will still start WP-Cron from page loads by default, with DISABLE_WP_CRON still the documented way out: the design exists for shared hosts that give no access to a system scheduler, and those hosts have not gone away. Confidence: Likely. Check by: Sep 2027.

What George's host found

His notes file this under the heading "Throttle cron jobs" and carry no date (the notes around it are from 2020 and 2021). His host's support team searched the site's access logs for wp-cron and counted the matching lines: 27,272. Their advice, in our words: WordPress starts its scheduler from visitors' page loads, that costs more as traffic grows, so switch the page-load trigger off and let the server's cron do the calling.

That number deserves a second look. WordPress does not send a new request to wp-cron.php on literally every page view. Its spawn_cron() function returns early when no task is due, and it refuses to start a second run within WP_CRON_LOCK_TIMEOUT seconds of the last one, which the source comments as 60 seconds. One site's own page loads can therefore start at most 1,440 runs in a day. George's 27,272 is 19 times that. The search in his notes covered every file whose name began with access.log, so it may have counted several days of rotated logs; a network of many sites sharing one log, or outside requests hitting wp-cron.php directly, would also raise it. His notes do not say which, and we cannot tell. The check on every page load is real either way, and so is the fix.

The fix, in two steps

1. Turn off the page-load trigger. Add this line to wp-config.php. Kinsta's guide (linked below) places it just above the comment that tells you to stop editing:

define( 'DISABLE_WP_CRON', true );

The handbook says that without it WordPress keeps running WP-Cron from page loads even after you add a scheduled job, which is wasted work. The constant does not delete or pause any scheduled task. It only stops visitors from being the clock, so step 2 is not optional: skip it and scheduled posts, update checks and plugin jobs stop running.

2. Give the server the job. On Linux or macOS, run crontab -e and add one line. The handbook's own example uses wget with --delete-after so the response is not saved:

*/15 * * * * wget --delete-after https://example.com/wp-cron.php

That calls the scheduler every 15 minutes; pick the interval your most time-sensitive task needs. On Windows the handbook's version is a Task Scheduler task that runs a PowerShell Invoke-WebRequest to the same address.

On managed hosting, check before you add anything. Kinsta's guide to disabling WP-Cron (updated Jun 8, 2026) says its servers already run a cron job for every site every 15 minutes, so a customer only needs the define line. WP Engine's event scheduling page (updated Jul 28, 2025) describes an "Alternate Cron" switched on from its portal that checks every minute, and warns that adding the line by hand does not switch it on. Two crons calling the same site is harmless but pointless; no cron at all is the failure to avoid.

What you trade

The handbook is fair to the default. With page-load cron, a task set for 2:00 PM on a quiet site may not run until the next visitor arrives hours later, but it will run. With a system cron, tasks run on time whether or not anyone visits, and the cost is that the schedule now depends on a crontab line that WordPress cannot see or repair. If that line is lost in a server move, nothing in the dashboard warns you.

George's own finding: the plugin script that needs a cd

After turning off page-load cron, George set up a second crontab line for a plugin that ships its own cron script, to run at minute 30 of every hour. His notes record both versions he tried.

Calling the script by its full path failed:

30 * * * * php /path/to/wordpress/wp-content/plugins/the-plugin/cron-script.php

PHP stopped on line 4 of the script with a warning that ends, in his notes, "failed to open stream: No such file or directory", then a fatal error. Line 4 was the script loading WordPress with require_once and the relative path ../../../wp-load.php.

Changing into the plugin's folder first worked:

30 * * * * cd /path/to/wordpress/wp-content/plugins/the-plugin && php cron-script.php

With the cd, his notes show the script starting and printing its own status message.

The reason is in PHP's manual. A path that begins with .. is looked up relative to the current directory, and command-line PHP does not change the current directory to the folder of the script it runs. Three levels up from a plugin's folder is the WordPress root, where wp-load.php lives. Three levels up from wherever cron happened to start is somewhere else.

This is why the bug hides. The natural way to test a cron script is to open a terminal, change into its folder and run it, and from there the relative path resolves. George's own test was run from inside the plugin's folder and got past line 4. The crontab line has no such starting point, so it fails where nobody is watching. A script that built the path from PHP's __DIR__ constant would not care where it was started, but that is the plugin author's choice, and the cd ... && prefix fixes it from your side without touching the plugin's code.

If a plugin's documentation gives a web address to call instead of a PHP file to run, this problem does not arise: PHP's manual shows that PHP started for a web request, unlike command-line PHP, changes into the script's own folder first.

How to tell it is working

  • Search the access log for wp-cron.php a day later. The requests should arrive at your chosen interval from the server itself, not in bursts that follow visitor traffic.
  • Schedule a post a few minutes ahead and see that it publishes with no one browsing the site.
  • For a plugin's own script, run the exact crontab command from your home directory, not from the plugin's folder. If it fails there, it fails in cron.
  • WP Engine's page suggests WP-CLI for stuck schedules: wp cron event list shows what is due, and wp cron event run --due-now runs it.

What was checked for this page

The define line, the every-page-load behavior, the wget example and the on-time versus eventually trade are from the two WordPress Plugin Handbook pages, read Nov 10, 2026. The 60-second lock and the due-task check are from the source of spawn_cron() printed on WordPress's code reference; the 1,440 a day and the factor of 19 are our arithmetic from it. The two hosts' intervals are from their own help pages as dated above. The 27,272 and both crontab attempts are from George's notes; we replaced his server paths, site and plugin names with placeholders, and we did not rerun his plugin's script, so the explanation of his error rests on PHP's manual and the path quoted in his error message.

Sources

See also

About this page

Last updated Nov 10, 2026 by the Vi.ki team. Page text CC BY-SA 4.0.

Edit History

Hotkeys

/
Jump to the search box
? or Ctrl + /
Open this list
Esc
Close this list, the photo viewer, or the account menu

Photo viewer

← → or A D
Previous or next photo
↑ ↓ or W S
Previous or next photo
Home End
First or last photo
I
Show or hide the photo's info
Z
Clickless on or off: a pointer over a thumbnail shows it
N
Compare with the last photo: back to the one shown before this, and N again comes back
Q
Move the thumbnails to the next edge: top, bottom, left and round
, or Ctrl + ,
Open or close the viewer's settings
V
Clickless pan: a zoomed photo follows the pointer, rather than being dragged
Shift
Browse on or off
B
Show or hide the button bar
T
Show or hide the thumbnails
1
100% zoom on or off
0
Rate the photo as no opinion; again takes the answer back
+ -
Rate the photo a step higher or lower
F
Full screen: the photo alone. F again puts everything back.
Back to top