Default WP-Cron relies on visitor page loads to trigger tasks. That slows down your frontend TTFB and silently drops scheduled jobs whenever traffic dips. The fix is simple: kill the virtual cron in wp-config.php and wire up a real system cron job inside Hostinger hPanel.
On busy sites, every single request can kick off a background POST request back to wp-cron.php. If ten visitors hit your site at once, WordPress might spawn ten identical background jobs. They lock database tables, exhaust your PHP-FPM workers, and spike server load. On the flip side, if no one visits your site between midnight and 6 AM, your scheduled backups, recurring WooCommerce subscriptions, and queued posts won’t run until someone finally drops by.
Handing this off to a proper server-level daemon solves both problems. Here’s how to set it up without breaking scheduled events.

Why Default WP-Cron Hurts Performance and Reliability
WordPress defaults to simulated cron because core developers back in 2007 couldn’t assume users had crontab access on cheap shared hosting. So whenever a user requests a page, WordPress checks the cron row in your wp_options table to see if anything is overdue.
If something is waiting, WordPress fires a non-blocking HTTP request back to itself at https://yourdomain.com/wp-cron.php. It sounds fine in theory, but in practice, it causes real headaches:
- PHP-FPM worker exhaustion: That self-request ties up an active PHP worker. On shared plans with strict process caps, those internal calls quickly starve real visitors of available workers.
- Sluggish TTFB: Spawning extra processes mid-render adds measurable overhead. On one 25-plugin WooCommerce store I worked on, turning off the virtual cron dropped median response times from 642ms down to 318ms.
- Missed schedules: Schedule a post for 4:00 AM, and if no one visits until 8:15 AM, your post sits unpublished for over four hours.
- Race conditions: A traffic spike can trigger multiple
wp-cron.phpruns in the exact same second, causing double-billed recurring charges, duplicated emails, or broken transient caches.
You can dig into the underlying queue architecture in the WordPress Developer Handbook on WP-Cron. Replacing that loop with Hostinger’s Linux crontab fixes all of this cleanly.
Step 1: Disable WP-Cron in wp-config.php
First, tell WordPress to stop checking the schedule on incoming web requests. It takes one line in your configuration file.
Head to Hostinger hPanel, go to Websites, pick your site, and open File Manager. Open your public_html folder, right-click wp-config.php, and select Edit.
Add this line directly above /* That's all, stop editing! Happy publishing. */:
// Disable virtual WP-Cron on page load
define('DISABLE_WP_CRON', true);Placement matters here. If you drop this below require_once ABSPATH . 'wp-settings.php'; at the bottom, WordPress has already loaded its runtime environment and will completely ignore the directive.
Prefer SSH? Hop into your terminal and append it using nano or sed. If you’re setting up crons alongside automated recovery routines, check our guide on how to restore a WordPress backup via SSH on Hostinger to get your CLI environment dialed in.
Step 2: Decide Between PHP CLI vs. cURL/Wget
Hostinger hPanel gives you two ways to invoke the cron job: direct command-line execution through PHP CLI, or an HTTP hit via curl or wget. Each has its place.
Method A: Direct PHP CLI Execution
Running wp-cron.php through the local PHP binary bypasses OpenLiteSpeed or Nginx entirely. It ignores web server execution limits, strips out network overhead, and doesn’t steal a slot from your web server’s worker pool.
On Hostinger shared and cloud plans, the PHP CLI path is typically /usr/bin/php (or version-specific like /usr/bin/php8.2). The full command looks like this:
/usr/bin/php /home/u123456789/domains/example.com/public_html/wp-cron.php >/dev/null 2>&1Method B: HTTP Trigger via cURL
Hitting the endpoint over HTTP mirrors how WordPress expects to be called. It ensures environment variables like $_SERVER['HTTP_HOST'] and SSL detection behave identically to a real browser visit.
curl -s -L "https://example.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1For most single-site setups on Hostinger, PHP CLI is the better choice—it’s faster and uses fewer web server resources. But if you run multisite subdirectories or complex reverse proxies that rely heavily on web-server-level environment variables, cURL can be simpler to maintain.
Step 3: Configure the Cron Job in Hostinger hPanel
Now, register the task in Hostinger’s control panel. In hPanel, go to Advanced > Cron Jobs.
You’ll see two tabs: Custom and PHP Script. Stick to Custom—it gives you full control over binary flags, absolute paths, and standard output redirection.
- Select Custom under Create a Cron Job.
- In Command to run, paste your full PHP binary path followed by the absolute path to your site’s
wp-cron.php. - Choose your frequency. For a typical blog, every 10 or 15 minutes is plenty. For active WooCommerce stores, every 5 minutes is safer.
- Click Save.
Here’s what I run on my own production setups in hPanel:
/usr/bin/php -q /home/u987654321/domains/isitdev.com/public_html/wp-cron.phpThe -q flag silences HTTP header output from PHP’s CLI, keeping logs clean. If you aren’t sure of your site’s absolute server path, look at the sidebar on that same Cron Jobs page or check Advanced > System Info.
One warning: if you run staging environments, make sure you don’t copy-paste production cron paths into staging configs. Walk through our tutorial on spinning up a WordPress staging site in Hostinger hPanel to keep staging and live crons separate.
Step 4: Verify the Cron Job Actually Runs
Don’t just assume the job works because hPanel saved the form. You need to verify that tasks are clearing out of the queue.
The easiest visual check is the free WP Crontrol plugin. Install it, activate it, and go to Tools > Cron Events.
At the top of the screen, you should see this notice:
The DISABLE_WP_CRON constant is set to true. WP-Cron spawning is disabled.
Next, look at the Next Run column for tasks like wp_version_check or action_scheduler_run_queue. If your cron is running properly, these will reset dynamically within your selected interval instead of showing “Past due”.
If you’re in an SSH session, you can inspect the event queue directly with WP-CLI:
wp cron event list --fields=hook,next_run_relative,recurrenceYou can also force a manual run from the command line to check for hidden fatal errors:
wp cron event run --due-nowIf that returns clean success output without throwing PHP fatals, your cron daemon and database queues are solid.
A Gotcha I Hit: 403 Forbidden and Hostinger ModSecurity
When I first set this up on an SSL-enforced site using the cURL method, scheduled posts refused to publish. My cron entry looked completely standard:
curl -s https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1I stripped out >/dev/null 2>&1 and redirected the output to a log file (>> /home/u123/cron.log 2>&1). Here’s what was happening:
403 Forbidden
403 Forbidden
OpenLiteSpeed
Hostinger’s ModSecurity rules flagged the default curl/7.x.x User-Agent hitting wp-cron.php as an automated bot and instantly blocked it with a 403 Forbidden.
Two ways around this:
- Switch to PHP CLI: Direct CLI calls run locally on the server and completely bypass OpenLiteSpeed and ModSecurity. It’s the cleanest fix.
- Spoof the User-Agent: If you must stick with cURL, pass a browser User-Agent string:</li
curl -A "Mozilla/5.0 (System Cron Daemon)" -s -L "https://example.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1If you run into redirect loops or certificate issues while setting this up, check our guide on how to fix WordPress mixed content errors on Hostinger.
Fine-Tuning Cron Intervals for Different Sites
Don’t set your cron to run every 60 seconds just because you can. On shared hosting, that burns through CPU seconds and can get your account throttled. Here is how I usually budget intervals:
- Simple blogs or portfolios: Every 15 to 30 minutes. Tasks are mostly checking for core updates or publishing an occasional scheduled draft. A 15-minute schedule keeps resource usage near zero.
- Standard WooCommerce stores: Every 5 to 10 minutes. WooCommerce depends on Action Scheduler for payment webhooks, receipt dispatches, and inventory updates. Five minutes is enough to keep orders moving without pegging the CPU.
- High-volume membership or LMS platforms: Every 2 to 5 minutes. You need prompt course progress updates and badge triggers. At that volume, make sure you also set up persistent caching—see our guide on how to configure Redis Object Cache on Hostinger to keep transient locks off your MySQL instance.
Frequently Asked Questions
How often should I run the real cron job in hPanel?
Every 10 to 15 minutes is ideal for standard websites. For active WooCommerce stores, go with 5 minutes. Avoid running it every 60 seconds on shared hosting plans—overlapping runs will burn through your resource limits.
Will scheduled posts fail if DISABLE_WP_CRON is true?
No, not if your system cron is working. Scheduled posts only fail if you disable virtual cron and forget to create the cron job in hPanel. Once the host-level cron runs, posts publish right on schedule.
Why does my cron job send me hundreds of empty emails?
Cron daemons email you anytime a command outputs text to STDOUT or STDERR. To silence these notifications, append >/dev/null 2>&1 to the end of your command in hPanel to discard standard output and errors.
Can I run WP-CLI commands in the Hostinger hPanel cron manager?
Yes, as long as WP-CLI is installed. You can paste commands like /usr/local/bin/wp cron event run --due-now --path=/home/u123456789/domains/example.com/public_html straight into hPanel’s custom command field.
Does disabling WP-Cron affect Action Scheduler in WooCommerce?
No. Action Scheduler hooks into standard WordPress cron events. When Hostinger triggers wp-cron.php, Action Scheduler picks up its pending queues and runs them automatically. You don’t need a separate server cron for WooCommerce.

