WP-Cron vs Real Cron: What’s the Difference?

WP-Cron is WordPress’s event scheduler, but it is not a continuously running system service. WordPress checks for due events during site requests, so execution can be late on low-traffic sites and can add contention on busy sites. A real system cron runs independently at configured times and can trigger WordPress predictably.

For a business-critical site, the usual production pattern is to disable request-triggered WP-Cron and run due WordPress events through a system scheduler every one to five minutes. That improves triggering reliability, but the jobs still need idempotency, locking, monitoring, and failure handling.

WP-Cron vs Real Cron: Key Differences

CharacteristicWP-CronSystem cron
TriggerWordPress request after an event is dueOperating-system or platform scheduler
TimingBest effortRuns on configured schedule
Traffic dependencyYes, by defaultNo
WordPress awarenessNative event queue and hooksMust invoke WordPress, WP-CLI, or an endpoint
Server accessNot requiredUsually required
ObservabilityLimited unless tooling is addedScheduler logs plus WordPress monitoring
Best fitPortable default for ordinary sitesPredictable production execution

The official WordPress Cron documentation explains that due tasks are checked on page loads. An event is therefore scheduled for “no earlier than” its timestamp, not guaranteed to execute at that exact second.

How WP-Cron Works

  1. A plugin, theme, or WordPress core schedules an event with a timestamp, hook, recurrence, and optional arguments.
  2. WordPress stores the event in its cron data.
  3. A later request checks whether an event is due.
  4. WordPress attempts to spawn cron processing.
  5. The registered hook callbacks execute.
  6. A recurring event is scheduled for its next interval.

Core uses scheduled events for update checks, scheduled posts, cleanup, privacy-related tasks, and other maintenance. Plugins use them for email, imports, synchronization, reports, license checks, and queue runners.

Where WP-Cron Fails Operationally

Low traffic causes late execution

If no request reaches the site after an event becomes due, nothing triggers the check. A scheduled post, import, or email may run late.

High traffic creates repeated spawn pressure

WordPress uses locking to reduce duplicate runners, but busy or unhealthy systems can still spend resources checking and spawning cron. Jobs then compete with visitors for PHP workers, CPU, database connections, locks, and memory.

Long work exceeds request limits

A cron callback still runs inside a PHP process. Large imports, exports, image processing, remote APIs, and queue backlogs can exceed execution or memory limits. Changing the trigger does not make an unbounded job safe.

Failures are easy to miss

WordPress does not provide a complete operations dashboard for every scheduled hook. A callback can fail repeatedly while the public site remains available. Monitor lateness, duration, error rate, attempts, and queue depth for important jobs.

How to Replace Request-Triggered WP-Cron with System Cron

First add this constant above the “stop editing” line in wp-config.php:

define( 'DISABLE_WP_CRON', true );

This disables spawning during normal requests. It does not delete events or stop the WordPress cron API. You must immediately provide another runner or scheduled work will stop.

Preferred: run due events with WP-CLI

*/5 * * * * cd /var/www/example.com/current && /usr/local/bin/wp cron event run --due-now --quiet

The official WP-CLI command reference documents wp cron event run --due-now. Adjust paths, user, PHP environment, container context, and multisite URL for the infrastructure. Do not run the command as root unless the deployment model specifically requires it.

Alternative: request wp-cron.php

*/5 * * * * curl --fail --silent --show-error --max-time 120 https://example.com/wp-cron.php?doing_wp_cron > /dev/null

The WordPress system scheduler guide documents this model. WP-CLI is generally easier to observe and avoids an external HTTP round trip, but some managed hosts expose only an HTTP scheduler.

How to Schedule WordPress Events Safely

Before scheduling a recurring event, check whether it already exists. WordPress explicitly recommends wp_next_scheduled() to prevent duplicates.

<?php
/**
 * Ensure the recurring event exists.
 */
function acme_schedule_sync(): void {
	if ( false === wp_next_scheduled( 'acme_hourly_sync' ) ) {
		wp_schedule_event( time(), 'hourly', 'acme_hourly_sync' );
	}
}
add_action( 'init', 'acme_schedule_sync' );

/**
 * Remove the event when the plugin is deactivated.
 */
function acme_deactivate(): void {
	wp_clear_scheduled_hook( 'acme_hourly_sync' );
}
register_deactivation_hook( __FILE__, 'acme_deactivate' );

The wp_schedule_event() reference notes that event arguments form part of the event identity. Mismatched arguments can create duplicates or prevent cleanup.

Design Cron Jobs for Reliability

  • Make jobs idempotent: retrying the same unit of work must not create duplicate charges, emails, or records.
  • Use bounded batches: process a limited number of records and schedule the next batch.
  • Prevent overlap: use an atomic lock with an expiry and release it in a finally path where possible.
  • Record progress: store durable cursors or job state instead of relying on process memory.
  • Set timeouts: external requests need explicit connection and response limits.
  • Classify failures: retry temporary failures with backoff; stop retrying invalid data indefinitely.
  • Log identifiers: record job, batch, object, attempt, duration, and result without leaking secrets.

WP-Cron vs Action Scheduler

Action Scheduler is a traceable WordPress job queue used by WooCommerce and other plugins. It adds action storage, status, logs, administration, retries, groups, and WP-CLI tooling. It still needs a runner, and its default runner is commonly triggered through WP-Cron.

The official Action Scheduler documentation positions it as a scalable job queue. For large or long-running queues, its WP-CLI documentation recommends the CLI runner over normal web requests.

Use caseRecommended tool
Small periodic maintenance hookWP-Cron API with system trigger
Large queue with retries and visibilityAction Scheduler
Infrastructure command or backupSystem cron directly
High-volume WooCommerce background workAction Scheduler with monitored WP-CLI runner

What to Monitor

  • Oldest overdue event
  • Failed actions and repeated attempts
  • Queue depth by hook or group
  • Job duration and memory use
  • Runner exit status and last successful invocation
  • Duplicate or overlapping execution
  • Business outcome, such as orders synchronized or emails sent

Cron problems often appear alongside high CPU, slow requests, and database contention. See why WordPress sites hit high CPU and how I audit WordPress performance before changing code.

For unreliable queues, recurring timeouts, or a WooCommerce site with growing scheduled actions, a WordPress technical architecture and reliability audit identifies the failure path and operating controls required.

Cron Behavior During Deployments and Migrations

Deployments can create duplicate or missing work when two application versions run at the same time. A rolling release may briefly have old and new workers reading the same queue. A migration may copy due events from production into staging, where they send real emails or call live integrations.

  • Disable outbound side effects on staging through environment-aware adapters, not by relying on people to remember.
  • Pause or drain sensitive queues before a database migration when job payloads or schemas change.
  • Make workers compatible with both the previous and current payload during rolling deployments.
  • Ensure only the intended environment owns the system-cron entry.
  • Verify the runner after domain, path, container, PHP-version, or hosting changes.
  • Document how to replay, cancel, or reconcile incomplete jobs after rollback.

WP-Cron on WordPress Multisite

Each site in a WordPress multisite network has its own scheduled events. A command that runs one site’s due events does not automatically prove every subsite is covered. Use the WP-CLI --url parameter or a controlled network loop and monitor results per site.

Large networks should avoid launching every site’s work simultaneously. Distribute execution, prioritize critical hooks, and set concurrency limits that protect the shared database and object cache. Record the site ID or URL in logs so failures can be traced to the correct tenant.

For any architecture, test the operational outcome. A scheduler reporting exit code zero only confirms that the runner completed; it does not confirm that payments renewed, feeds imported, reports generated, or notifications reached their destination.

Connect technical monitoring to a business reconciliation check so silent partial failures become visible before customers or operators report them.

Frequently Asked Questions

Is WP-Cron a real cron job?

No. WP-Cron is WordPress’s scheduling API and event queue. By default, WordPress checks and spawns due work from site requests instead of a continuously running operating-system scheduler.

Should I disable WP-Cron?

Disable request-triggered WP-Cron when the site needs predictable execution and you can configure a reliable replacement runner. Never enable DISABLE_WP_CRON without immediately adding and testing that runner.

How often should system cron run WordPress events?

One to five minutes is common for sites with time-sensitive tasks. Choose an interval based on the tightest real requirement, workload, and hosting limits. Running the trigger every minute does not guarantee a long job completes every minute.

Does system cron make WordPress jobs faster?

It makes triggering more predictable and can move execution away from visitor requests. It does not fix inefficient callbacks, slow APIs, missing indexes, overlapping jobs, or unbounded batches.

Is Action Scheduler a replacement for WP-Cron?

Action Scheduler replaces the job-queue layer for suitable workloads, but it still needs a process that runs due actions. Its default runner commonly uses WP-Cron; high-volume sites can run the queue with WP-CLI.

Why are scheduled posts late in WordPress?

Late posts can occur when no request triggers WP-Cron after the scheduled time, loopback requests fail, cron is disabled without a working runner, or the event queue is blocked by errors or resource pressure.

Mehul Gohil
Mehul Gohil

Mehul Gohil is a Full Stack WordPress developer and an active member of the local WordPress community. For the last 13+ years, he has been developing custom WordPress plugins, custom WordPress themes, third-party API integrations, performance optimization, and custom WordPress websites tailored to the client's business needs and goals.

Articles: 162

Leave a Reply

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