WordPress Cron Job Debugger
Disable slow virtual wp-cron visitor execution and generate optimized Linux server crontab commands for reliable background tasks.
define('DISABLE_WP_CRON', true);*/10 * * * * wget -q -O - https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
Understanding WordPress Virtual WP-Cron vs. System Crontab
1. How Virtual WP-Cron Actually Operates
WordPress does not use your server's real crontab by default. Instead it relies on a pseudo-cron system: every front-end page load calls an internal spawn_cron() check, which scans the wp_options table for any scheduled hook — a queued post publish, a plugin backup, a WooCommerce subscription renewal — whose timestamp has already passed. If it finds one, WordPress fires a non-blocking internal HTTP loopback request to wp-cron.php and executes the due hooks before finishing the visitor's response. WordPress throttles this check to roughly once per request cycle rather than on literally every page view, but the entire mechanism still depends on someone loading a page. As documented in the WordPress Cron API Documentation, this trade-off exists so shared hosting without shell access can still run scheduled tasks — at the cost of timing precision.
2. Why "wp-cron Not Running" Usually Isn't a Bug
A report of wp-cron not running is almost always a traffic or caching side effect, not a broken PHP function. Because spawn_cron() only fires from a genuine front-end HTTP request, three situations reliably stop it cold:
- Low-traffic windows: a site with no visitors between 2 a.m. and 6 a.m. never triggers
wp-cron.phpin that window, so anything scheduled for 3 a.m. silently waits for the next visitor. - Full-page caching or a CDN edge cache: if every request is served from a cache layer before WordPress ever bootstraps PHP,
spawn_cron()never executes at all. - Password-protected or maintenance-mode staging sites: authentication walls block the front-end requests that would otherwise trigger the check.
In none of these cases is the scheduled event itself corrupted — it simply isn't being asked to run. Replacing visitor-triggered cron with the real system cron entry generated above removes that dependency entirely, which is why it's the standard fix agencies and developers reach for first.
3. Performance & TTFB Latency Penalties
Because the wp-cron.php check runs as part of WordPress bootstrapping on the page that happens to trigger it, sites with many scheduled tasks or slow database queries can see a measurable Time to First Byte (TTFB) penalty on that specific request — worse still on hosting without persistent object caching, where the check requires the same uncached wp_options lookups as every other query. Sites running WooCommerce, backup plugins, or SEO plugins that register dozens of hourly or daily hooks are the most affected, since more scheduled events mean more frequent triggering. Estimate how much of that overhead is coming from stale plugin data in our Database Size Analyzer, which flags orphaned transients and postmeta bloat that often accumulate alongside heavy cron usage.
4. Configuring a Real Linux Server Crontab
Once DISABLE_WP_CRON is set to true, WordPress will never spawn its own loopback request again — you become responsible for triggering wp-cron.php externally on a fixed interval. The generator above builds a standard crontab line using wget in quiet mode, discarding output so the job doesn't email you on every run. To install it, SSH into your server, run crontab -e, paste the generated line, then save and exit; most VPS and dedicated hosts support this directly. On shared hosting without SSH access, look for a "Cron Jobs" panel in cPanel or Plesk and paste the same URL pattern into their scheduled-task UI instead of a raw crontab line.
As an example, a domain of agencyclient.com with a 15-minute interval produces */15 * * * * wget -q -O - https://agencyclient.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1, which hits the endpoint 96 times a day regardless of actual visitor traffic. If wget isn't available on your host, curl -s works identically. Some managed WordPress hosts (WP Engine, Kinsta, Pantheon) already run a system-level trigger for you and disable visitor-triggered cron automatically at the platform level — check with your host before adding a duplicate entry. Calculate plugin execution weights in our Plugin Bloat Score Calculator.
5. Diagnosing Missed Cron Events & Common Mistakes
This generator produces the correct configuration snippets, but it doesn't perform a live scan of your site's actual cron queue — confirming whether events are genuinely overdue requires a separate check. WP-CLI users can run wp cron event list to see every scheduled hook alongside its next-run timestamp and immediately spot anything showing a negative "due" value. Site owners without shell access can install the free WP Crontrol plugin, which surfaces the same list inside wp-admin and lets you manually run or delete a stuck event.
This combination is useful in a few concrete scenarios: an agency running a pre-launch checklist to confirm scheduled posts and subscription renewals will fire reliably before a low-traffic staging site goes live, a developer troubleshooting why a client's nightly backup plugin silently skipped several days in a row, or a site owner who noticed scheduled blog posts consistently publish hours late and wants to rule out traffic-dependent cron before opening a support ticket.
A few limitations are worth knowing. Disabling virtual cron and forgetting to add the replacement crontab entry leaves every scheduled task completely stalled, which is worse than the default behavior — always add both generated snippets together, never the wp-config.php constant alone. The wget command also assumes your server allows outbound loopback requests to its own domain; some locked-down firewalls block this, in which case curl or a dedicated WP-CLI cron call is a safer substitute. Finally, changing the interval here only changes how often the trigger fires — it doesn't change how often an individual scheduled hook executes, since that's still governed by the interval registered in the plugin or theme code that originally scheduled it.
6. Decoupling Cron Overhead via Nimbica Static Edge
Nimbica pre-renders WordPress pages into static HTML served from 300+ global edge locations, so visitor requests complete instantly regardless of whether wp-cron is mid-execution in the background. Because static edge delivery never touches PHP on a per-visitor basis, cron overhead is fully isolated from the pages your visitors actually load — background jobs keep running on your origin server without ever affecting the TTFB the public sees.
Decouple background tasks from visitor load times with Nimbica
Transform dynamic PHP rendering bottlenecks into ultra-fast static HTML deployed across 300+ global edge locations.
Frequently Asked Questions
How does virtual wp-cron work and why does it slow down visitor page loads?
Virtual wp-cron hooks into visitor page requests. When a user loads a page, WordPress checks if scheduled tasks are due and spawns an internal HTTP request to wp-cron.php, increasing server TTFB.
Why should I disable virtual wp-cron and use a real server cron job?
Disabling virtual wp-cron (`define("DISABLE_WP_CRON", true);`) and setting up a server cron job (crontab) ensures scheduled tasks run reliably in the background without penalizing visitor page load speeds.
What server crontab command should I use for WordPress?
Use: `*/10 * * * * wget -q -O - https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1` to trigger wp-cron every 10 minutes from Linux server crontab.
Related Tools in This Cluster
WordPress Database Size Analyzer
Estimate database table growth and overhead caused by plugin transients.
WordPress Plugin Bloat Score Calculator
Calculate page weight and CPU execution impact caused by active plugins.
WordPress Plugin Conflict Checker
Diagnose known WordPress plugin conflicts and script collisions.
