New: Get 2 months free on any annual plan. Claim offer →

Managing Cron Jobs in WordPress: WP-Cron vs. Real Server Cron

Managing cron jobs in WordPress comes down to a single decision: let WP-Cron fire on visitor page loads, or hand the schedule over to a real cron job on the server. WP-Cron is a simulated scheduler, not a system daemon, so it only wakes up when traffic arrives. On a site with steady traffic that distinction rarely matters, and on a quiet site it quietly breaks scheduled posts, backups, and abandoned-cart emails.

WP-Cron Only Runs When Someone Visits

Every front-end and admin request in WordPress checks whether any scheduled task is overdue. If one is, WordPress fires a non-blocking loopback request to wp-cron.php, which then runs the due events in a separate PHP process. The WordPress developer documentation on Cron describes this as the reason WP-Cron is time-approximate rather than time-accurate.

A typical WordPress install carries 25 to 60 registered events: update checks, transient cleanup, sitemap pings, plugin licence checks, and whatever your theme adds. WooCommerce sites add Action Scheduler on top, which can queue thousands of rows in a busy month. All of that sits in a single cron option in the database until something triggers it.

Where WP-Cron Starts Causing Real Problems

The failure modes are predictable once you know what the mechanism depends on. Each one shows up differently in the logs, which is why cron issues get misdiagnosed as plugin bugs.

  • Low traffic sites miss schedules entirely. A brochure site with 12 visits a day may publish a 9:00 AM scheduled post at 2:40 PM, whenever the next visitor happens to land.
  • High traffic sites pay an overhead tax. Thousands of page loads mean thousands of cron checks and repeated loopback spawns, which eats PHP workers during peak periods.
  • Full-page caching hides the trigger. If a CDN or LiteSpeed cache serves most requests without touching PHP, WP-Cron never gets a chance to run.
  • Loopback requests fail. Firewalls, basic auth on staging, or a mismatched hostname will block the internal request to wp-cron.php with no visible error.
  • Concurrent runs collide. Two overlapping spawns can double-send an email or duplicate an import, especially on sites with slow long-running jobs.

When a job hangs mid-run, the symptom is often a timeout rather than a missed schedule, which overlaps with the causes behind 504 gateway timeout errors in WordPress.

What a Real Server Cron Job Does Differently

A real cron job is a line in the server crontab, executed by the operating system at a fixed interval whether or not a single visitor shows up. It runs at the same time every day, runs exactly once, and writes its output somewhere you can read. That reliability is the whole reason to switch.

The trade-off is small: you take on one configuration step and one monitoring responsibility. In exchange, a 3:00 AM backup happens at 3:00 AM, and a scheduled post goes live within your chosen interval instead of whenever traffic arrives.

Switching From WP-Cron to a Server Cron in Four Steps

  1. Disable the built-in spawner. Add define('DISABLE_WP_CRON', true); to wp-config.php, above the line that says stop editing. This stops the page-load trigger but leaves the schedule intact.
  2. Add the crontab entry. Something like */5 * * * * cd /home/user/public_html && wp cron event run --due-now >/dev/null 2>&1 runs every five minutes.
  3. Verify the first run. Wait one interval, then check wp cron event list and confirm the next-run timestamps have moved forward.
  4. Restrict public access. Once the server handles the schedule, block or rate-limit direct hits to wp-cron.php so nobody can hammer it from outside.

If your host only exposes a cPanel cron interface, the same result comes from a wget call to https://example.com/wp-cron.php?doing_wp_cron with output discarded.

WP-CLI Beats a Curl Request in Most Cases

Both methods work, but they are not equivalent. A wget or curl request goes through the web server, inherits the PHP-FPM timeout, and counts against your worker pool. WP-CLI runs under the CLI PHP binary, which usually has a higher or unlimited max_execution_time and more memory, per the official WP-CLI cron command reference.

We cover this topic in more depth in Composer in WordPress: Managing Dependencies on the Server.

Related reading: Using Generative AI to Optimize WordPress Server Configurations.

For long jobs such as an ecommerce export or a large Action Scheduler batch, that difference decides whether the task finishes. The HTTP method still has a place: it is the only option on shared plans without SSH. Anyone already working in the terminal can pair this with the wider toolkit covered in our WP-CLI guide for WordPress server management.

Auditing What Is Actually in Your Cron Queue

Most guides stop at the crontab line, which leaves the more expensive problem untouched: nobody knows what those jobs are doing. Run wp cron event list --fields=hook,next_run_relative,recurrence on any site that has been live for two years and you will usually find several orphaned hooks from deleted plugins.

Three things are worth checking quarterly:

  • Orphaned hooks from plugins that were removed without cleanup, which fire, find no callback, and waste a process.
  • Over-frequent schedules, such as a licence check set to every_minute that only needs to run daily.
  • Stacked duplicates, where the same hook appears five times because an upgrade routine re-registered it.

On content-heavy publishing setups the cumulative cost is real, which is one reason our WordPress magazine hosting plans keep cron execution off the visitor request path entirely. Portfolio and gallery sites on hosting built for creatives see the same benefit during image regeneration runs.

Monitoring Cron So Silent Failures Get Noticed

A cron job that stops running produces no error page and no support ticket until a client asks why last week’s backup is missing. Redirect the crontab output to a log file instead of /dev/null during the first fortnight, then review what accumulates. Pair that with the habits in our walkthrough on monitoring WordPress PHP error logs on the server.

Dead-man switch services such as Healthchecks or Cronitor add a ping at the end of the command and alert you when the ping stops arriving. For a broader view of load patterns and which hours your background tasks compete with traffic, WordPress hosting analytics gives you the timing data to move heavy jobs into a quieter window.

Agencies running dozens of installs should standardise the interval and the log path across every site, the same way you would standardise updates when bulk managing WordPress plugins across 50+ client sites.

Choosing an Interval That Matches the Site

Five minutes suits most business and blog installs, and it keeps scheduled posts within a tolerable margin. Stores processing subscriptions or stock syncs usually want every minute, because Action Scheduler processes batches and a slow cadence lets the queue build. A static-ish brochure site is fine at fifteen minutes.

Set the interval lower than your shortest recurring event, never higher. A job registered as hourly with a cron running every two hours will drift by an hour, every time.

Frequently Asked Questions

Does Disabling WP-Cron Break Scheduled Posts?

No, provided a real cron job runs at least every 15 minutes. DISABLE_WP_CRON only stops the page-load trigger; the schedule itself stays in the database and executes normally when the server calls it. Posts go live within one interval of their set time.

Is wp-cron.php a Security Risk?

It can be, because the file is publicly reachable and every request forces PHP to execute. Attackers use repeated calls as a cheap resource-exhaustion tactic, so block or rate-limit the file at the firewall once a server cron takes over. Server-level rules like the ones in our WordPress hosting security setup handle this automatically.

What Is ALTERNATE_WP_CRON For?

It is a fallback for hosts where the internal loopback request fails, used on maybe 5% of installs. Instead of a background request, it redirects the visitor’s browser to trigger the cron run, which can produce odd URLs in the address bar. A real server cron is the better fix in almost every case.

Can I Run Cron Jobs on Shared Hosting?

Yes, most shared plans include a cron manager in cPanel with a minimum interval of one or five minutes. Without SSH you will use a wget call rather than WP-CLI, which works fine for short jobs but can time out on large batches.

Put Your WordPress Cron Jobs on a Real Schedule

Our team sets up server-level cron, sensible intervals, and failure alerts as part of onboarding, so scheduled tasks run on time without touching your PHP workers. Talk to WebVibo about moving your site, and we will audit the existing cron queue while we are in there.

← Previous How to Monitor WordPress PHP Error Logs on the Server

3 Comments

  1. Server-Side Tracking for GA4 in WordPress: Setup Guide

    […] Related reading: Managing Cron Jobs in WordPress: WP-Cron vs. Real Server Cron. […]

  2. Optimize the WordPress REST API for Headless Apps

    […] schedule to a real server cron running every one to five minutes, as covered in our breakdown of WP-Cron versus real server cron. Heavy jobs like image regeneration or search indexing belong in a queue worker, not inside the […]

  3. Un-suspend a WordPress Site Overusing CPU Resources

    […] documentation on cron explains why the default behaviour scales badly, and our breakdown of WP-Cron versus real server cron covers the setup in […]

Leave a Comment

Your email address will not be published. Required fields are marked *