What WP-Cron actually does
The WordPress developer handbook says WP-Cron "works by checking, on every page load, a list of scheduled tasks to see what needs to be run," and that it "does not run constantly as the system cron does." Nothing in WordPress wakes up at 9:00 to release a lesson. The release happens inside whatever request arrives after 9:00.
The handbook gives its own example: a task scheduled for 2:00 PM can wait until 5:00 PM if no page loads happen in between. It also says the task will run eventually. Missed events are not dropped; they run late. That is the trade-off: delivery is reliable, timing is not.
Plugins schedule events on recurrences such as hourly, twicedaily, daily and weekly (weekly was added in WordPress 5.4), or as one-off events at a timestamp. LMS and membership plugins can use these hooks for drip schedules, access expiry, certificate generation and reminder emails, so all of them inherit the page-load dependency.
Why course sites feel this more than blogs
A blog that publishes a post twenty minutes late rarely notices. A course site sells time-based promises: "Module 3 unlocks on day 7", "your access ends on the 31st", "renewal reminder three days before billing". When those slip, students email support or, worse, keep access they should have lost.
Course sites are often quiet at exactly the wrong times. Traffic clusters around launches and live sessions, then drops overnight and between cohorts. Many requests also never reach WordPress: hosts and caching plugins serve anonymous pages from cache, so a visitor reading a cached sales page may not trigger PHP at all. The fewer uncached PHP requests you get, the less often WP-Cron gets a chance to run.
The opposite problem appears on busy sites. Kinsta notes that wp-cron.php fires on every page load by default, which can cause problems on high-traffic sites, and that because the file is public, someone can request it repeatedly to spike server load. A server cron fixes both: tasks run on a timetable, and ordinary page views stop doing scheduler work.
| Scheduled task | What a late run looks like to a student | Severity |
|---|---|---|
| Drip lesson release | Lesson still locked hours after the promised time | Support tickets, refund requests on cohort courses |
| Membership or course access expiry | Expired members keep access until the next visit triggers cron | Revenue leakage |
| Renewal or payment reminder email | Reminder arrives after the card is charged | Chargebacks and complaints |
| Scheduled sale price start or end | Discount starts late or runs past its deadline | Pricing errors |
| Certificate or report generation queued by a plugin | Certificate email delayed | Low, but visible |
The fix: disable the page-load trigger, add a timetable
The pattern is the same on every host. First give the site a reliable trigger, then stop page loads from doing the work. Kinsta warns about the order: if you disable WP-Cron without a replacement, scheduled tasks stop running without any error.
Step one is a server-side schedule that requests wp-cron.php or runs due events through WP-CLI. The developer handbook shows a crontab entry using wget with --delete-after and the */15 syntax for a 15-minute schedule. SiteGround's tutorial instead runs WP-CLI from the site directory: cd into the WordPress path, then wp cron event run --due-now, with output sent to /dev/null.
Step two is one line in wp-config.php: define( 'DISABLE_WP_CRON', true ); placed above the "stop editing" comment. WordPress's wp-config documentation also lists WP_CRON_LOCK_TIMEOUT, which stops a cron process from running more than once per that many seconds (its example is 60), and ALTERNATE_WP_CRON, which it describes as a fallback for scheduled posts that do not publish, with "certain risks". On a host with a real scheduler, DISABLE_WP_CRON plus the server job is the documented route.
- Add the server job first, confirm it runs, then add DISABLE_WP_CRON.
- Pick an interval that matches your tightest promise. If lessons unlock "at 9:00", a 30-minute schedule means up to 9:30.
- Check the result in WP-CLI with wp cron event list, which Kinsta suggests for verification, and look for events whose next run time is in the past.
- If you run multisite, test each subsite: Kinsta notes a single server cron pointed at the main domain may not reliably fire subsite jobs.
What each host documents
The four hosts take very different approaches, from "already done for you" to "you own the crontab". The table summarises their own documentation.
| Host | Server-side trigger | Documented frequency | Who sets it up | Notes from the docs |
|---|---|---|---|---|
| Kinsta | Platform server cron on every site; custom jobs via SSH crontab | Platform job every 15 minutes; custom jobs no more often than every 5 minutes | Kinsta runs the platform job; you add DISABLE_WP_CRON. Support can add custom jobs you supply | Add custom jobs at the bottom of the crontab; the top is managed by Kinsta and may be overwritten |
| WP Engine | Alternate Cron, a server-side service that requests wp-cron.php | Checks for due events every minute | Toggle under Utilities for the environment in the User Portal | Sets DISABLE_WP_CRON automatically; adding the define yourself does not enable it. Does not work behind basic auth or other custom password protection; WP Engine says it does not technically support true server crons |
| SiteGround | Cron job in Site Tools > Devs > Cron Jobs running WP-CLI | 30 minutes ("Twice Per Hour" preset) suggested as fine for most sites | You | Fair-use guidance asks for at least 30 minutes between scheduled script runs; append >/dev/null 2>&1 to avoid an email per run |
| DigitalOcean Droplet | System crontab on your own server | Any interval you choose | You, as root | The WordPress 1-Click image is Ubuntu 24.04 with WP-CLI installed and SSH access; cron setup is not covered by that page |
Worked example: a cohort course with 9:00 unlocks
Suppose a course unlocks one module each morning at 9:00 and emails students that it is live. On a typical weekday the first logged-in student arrives at 9:40, so with plain WP-Cron both the unlock and the email happen at 9:40. On a quiet Sunday the first uncached request might not come until early afternoon.
On Kinsta the platform cron runs every 15 minutes, so the unlock lands by about 9:15 once DISABLE_WP_CRON is set. On WP Engine with Alternate Cron enabled, the check runs every minute. On SiteGround with the suggested 30-minute job, expect the unlock by 9:30. On a Droplet you can choose a 5-minute crontab, but you are also the person who notices when it stops.
If the promise matters to the hour, schedule the unlock a few minutes before the published time rather than tightening the cron interval. On SiteGround especially, a more frequent job runs against the fair-use guidance.
Checklist after a migration or host change
Cron is one of the settings that silently changes during a move. wp-config.php may carry DISABLE_WP_CRON across to a host where no server job exists, or the new host may need a toggle you have not flipped.
- Search wp-config.php for DISABLE_WP_CRON and confirm a matching server job exists on the new host.
- On WP Engine, check the Alternate Cron toggle for each environment; staging and production are configured separately.
- On SiteGround, re-create the Site Tools cron job with the new install path; the path is part of the command.
- On a Droplet, run crontab -l as the user that owns the job and confirm the URL or path points at the new site.
- Run wp cron event list and look for overdue events.
- Add a heartbeat monitor that the cron job pings after each run, so a stopped scheduler raises an alert instead of a support ticket.
Questions before you decide
Does WP-Cron skip tasks if nobody visits?
No. The WordPress developer handbook says missed tasks run at the next opportunity, so they run late rather than not at all. A system scheduler, by contrast, does not retry a run it missed.
Do I need to disable WP-Cron on Kinsta?
Kinsta says it runs a server cron on all sites every 15 minutes, so you can skip creating one and only add DISABLE_WP_CRON to wp-config.php. You can add custom server cron jobs over SSH, but not more often than every 5 minutes.
How do I get a real cron on WP Engine?
Turn on Alternate Cron for the environment under Utilities in the User Portal. It checks for due events every minute and sets DISABLE_WP_CRON for you. Adding the define yourself does not enable it, and it does not work behind basic auth.
How often should a SiteGround cron job run?
SiteGround's tutorial suggests every 30 minutes using the Twice Per Hour preset, and its fair-use guidance recommends at least 30 minutes between scheduled script runs.
Sources & verification
Product details and prices can change. Check the linked provider before buying.
- WordPress developer handbook: Cron Accessed 30 Oct 2026
- WordPress developer handbook: hooking WP-Cron into the system task scheduler Accessed 30 Oct 2026
- WordPress developer handbook: understanding WP-Cron scheduling Accessed 30 Oct 2026
- WordPress developer handbook: editing wp-config.php Accessed 30 Oct 2026
- Kinsta: how to disable WP-Cron Accessed 30 Oct 2026
- Kinsta blog: how to disable WP-Cron for faster performance Accessed 30 Oct 2026
- Kinsta docs: cron jobs Accessed 30 Oct 2026
- WP Engine: event scheduling and WP-Cron Accessed 30 Oct 2026
- SiteGround: how to replace the WordPress cron with a real cron job Accessed 30 Oct 2026
- SiteGround KB: manage cron jobs in Site Tools Accessed 30 Oct 2026
- SiteGround KB: fair use of server resources Accessed 30 Oct 2026
- DigitalOcean docs: WordPress 1-Click App Accessed 30 Oct 2026
Sources link directly to providers. Product buttons may use separately labeled affiliate links. Read our disclosure.