In WordPress, scheduled posts, update checks, backups and WooCommerce's deferred actions all run through WP-Cron. Despite the name, it isn't a real scheduler: it is checked only when someone opens a page. On each request WordPress looks for due tasks and, if there are any, fires a background request to wp-cron.php. That works anywhere with zero setup, but it has real drawbacks.
Where WP-Cron falls short
On low-traffic sites nothing runs until a visitor arrives, so a post scheduled for 7:00 may appear after the first morning visit — or show "Missed schedule". Backups and newsletters slip the same way. On busy sites the check runs on every page view and wp-cron.php keeps getting called, tying up PHP workers at peak times. With full-page caching PHP may not run at all, so WP-Cron is never checked. A server cron job fixes all three: it ignores traffic and runs on time as a single process.
Step 1: turn off the page-load trigger
Add this to wp-config.php above the "That's all, stop editing!" comment:
define( 'DISABLE_WP_CRON', true );
This does not delete any tasks; it only stops WordPress from calling wp-cron.php on page loads. Don't skip step 2, or nothing scheduled will run.
Step 2: add a server cron job
Run wp-cron.php through PHP CLI so it bypasses the web server:
*/5 * * * * cd /var/www/user/data/www/example.uz && /usr/bin/php wp-cron.php >> /var/www/user/data/logs/wp-cron.log 2>&1
With WP-CLI available, this runs only due events and prints readable output:
*/5 * * * * cd /var/www/user/data/www/example.uz && /usr/local/bin/wp cron event run --due-now >> /var/www/user/data/logs/wp-cron.log 2>&1
Check binary paths with which php and which wp, and point cron at the same PHP version the site uses; otherwise newer plugins may throw syntax errors under an older interpreter. Keep the log redirect for the first few days so you can see any PHP warnings, then trim or rotate the file. Running through CLI also means the job is not subject to web-server timeouts, which helps long backup or import tasks finish instead of being cut off halfway.
Choosing a frequency
A news or school site is fine at 5–10 minutes. WooCommerce's Action Scheduler queue runs through the same mechanism, so a busy shop may want 1–2 minutes. A brochure site can use 15–30. Prefix with flock -n /tmp/wpcron.lock to stop long runs overlapping.
Step 3: verify
cd /var/www/user/data/www/example.uz
wp cron event list --fields=hook,next_run_relative
wp cron test
If next-run times keep moving forward rather than sticking in the past, it works. Without WP-CLI, a plugin such as WP Crontrol shows the list in the admin area. Scheduling a test post 10 minutes ahead and watching it go live on time is a good final check, and a glance at the log after a few hours confirms there are no PHP errors.
Example: a school website
A private school in Samarkand scheduled announcements for 7:30 a.m., when parents got the link via a Telegram channel. With almost no night traffic, posts went live after 8 or showed "Missed schedule". After enabling DISABLE_WP_CRON and a five-minute server cron, announcements appeared within minutes of schedule, and the backup plugin began running on time every night.
Common mistakes
- Setting
DISABLE_WP_CRONwithout adding a server cron job. - Forgetting
cd, sowp-cron.phpcan't find WordPress. - Placing the line below "stop editing", where it has no effect.
- On multisite, running cron only for the main site instead of each site with
--url.
On sayt.uz hosting you add the job in the Scheduler section of ISPmanager, opened from the sayt.uz cabinet. If you can't find the WP-CLI or PHP path, open a support ticket.