DEV Community

Cover image for WordPress Cron Explained (Real-World Guide After 6 Years)
MD Hemal Akhand
MD Hemal Akhand

Posted on

WordPress Cron Explained (Real-World Guide After 6 Years)


If you’ve built WordPress features that should run in the background, you’ve probably hit this:

  • Email should send every hour → doesn’t
  • Cleanup should run nightly → skips
  • One-time reminder after signup → never fires

The code looks fine. Local works. Production doesn’t.

After 6 years building WordPress themes, plugins, and WooCommerce projects, I can tell you: most cron issues are not syntax errors. They’re misunderstanding how WordPress scheduling works.


What is a scheduled task in WordPress?

A scheduled task is a job WordPress runs later — automatically.

Examples:

  • Send reminder emails
  • Clean old logs
  • Sync data to a CRM
  • Fire a one-time follow-up after purchase

WordPress calls this system WP Cron.


WP Cron ≠ Server Cron

Server cron runs at an exact time (e.g. 3:00 AM daily).

WP Cron runs based on traffic.


WP Cron behavior

Site type Behavior
High traffic Reliable
Low traffic Delayed
Staging Unpredictable

The mental model

Schedule → Hook name → add_action() → Function runs
Enter fullscreen mode Exit fullscreen mode

The 2 functions you’ll use most

// Check if already scheduled
wp_next_scheduled( $hook, $args );

// Schedule repeating task
wp_schedule_event( $timestamp, $recurrence, $hook, $args );
Enter fullscreen mode Exit fullscreen mode

Safe pattern

  • wp_next_scheduled() → check first
  • wp_schedule_event() → schedule
  • add_action() → connect callback

1. Repeating task (hourly email)

Hook registration

add_action( 'butterfly_hourly_email_hook', 'butterfly_send_email_func' );
Enter fullscreen mode Exit fullscreen mode

Schedule it

function butterfly_create_cron_event() {

    $args = [
        'hemal.akanda.39@gmail.com'
    ];

    if ( ! wp_next_scheduled( 'butterfly_hourly_email_hook', $args ) ) {

        wp_schedule_event(
            time(),
            'hourly',
            'butterfly_hourly_email_hook',
            $args
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Callback

function butterfly_send_email_func( $email ) {

    wp_mail(
        sanitize_email( $email ),
        __( 'Reminder', 'butterfly-cron' ),
        __( 'Hey Butterfly. Its a custom message from butterfly', 'butterfly-cron' )
    );
}
Enter fullscreen mode Exit fullscreen mode

2. One-time task

add_action( 'butterfly_single_event_hook', 'butterfly_send_email' );

function schedule_single_event() {

    $args = [
        'hemal.akanda.39@gmail.com'
    ];

    if ( ! wp_next_scheduled( 'butterfly_single_event_hook', $args ) ) {

        wp_schedule_single_event(
            time() + 3600,
            'butterfly_single_event_hook',
            $args
        );
    }
}

function butterfly_send_email( $email ) {

    wp_mail(
        sanitize_email( $email ),
        __( 'Send a email subject', 'butterfly-cron' ),
        __( 'Send email message', 'butterfly-cron' )
    );
}
Enter fullscreen mode Exit fullscreen mode

3. Remove a scheduled task

function butterfly_schedule_an_event() {
    wp_schedule_event( time(), 'hourly', 'butterfly_schedule_an_wp_event' );
}

add_action( 'butterfly_schedule_an_wp_event', 'butterfly_create_an_wp_event' );

function butterfly_unschedule_an_event() {

    $timestamps = wp_next_scheduled( 'butterfly_schedule_an_wp_event' );

    if ( $timestamps ) {
        wp_unschedule_event( $timestamps, 'butterfly_schedule_an_wp_event' );
    }
}

function butterfly_create_an_wp_event() {

    wp_mail(
        sanitize_email( 'hemal.akanda.39@gmail.com' ),
        __( 'Create a meetup on wordpress in dhaka', 'butterfly-cron' ),
        __( 'Hey! Lets create a meetup for WordPress Community in Dhaka/Bangladesh', 'butterfly-cron' )
    );
}
Enter fullscreen mode Exit fullscreen mode

4. Custom intervals

add_filter( 'cron_schedules', 'butterfly_cron_schedule' );

function butterfly_cron_schedule( $schedules ) {

    $schedules['weekly'] = [
        'interval' => 604800,
        'display'  => __( 'Once a week', 'butterfly-cron' )
    ];

    return $schedules;
}
Enter fullscreen mode Exit fullscreen mode

Use it

wp_schedule_event( time(), 'weekly', 'my_weekly_hook' );
Enter fullscreen mode Exit fullscreen mode

5. Debug scheduled tasks

$cron = _get_cron_array();
$all_schedules = wp_get_schedules();
?>

<?php foreach ( $cron as $timestamp => $hooks ) : ?>

    <?php foreach ( (array) $hooks as $hook => $events ) : ?>

        <?php foreach ( (array) $events as $event ) : ?>

            <tr>

                <td>
                    <?php echo date_i18n( 'M j, Y @ G:i', wp_next_scheduled( $hook ) ); ?>
                </td>

                <td>
                    <?php echo ! empty( $event['schedule'] )
                        ? esc_html( $all_schedules[ $event['schedule'] ]['display'] )
                        : 'Once'; ?>
                </td>

                <td>
                    <code><?php echo esc_html( $hook ); ?></code>
                </td>

            </tr>

        <?php endforeach; ?>

    <?php endforeach; ?>

<?php endforeach; ?>
Enter fullscreen mode Exit fullscreen mode

Quick reference

  • wp_schedule_event() → repeating task
  • wp_schedule_single_event() → one-time task
  • wp_next_scheduled() → check exists
  • wp_unschedule_event() → remove task
  • cron_schedules → custom intervals

Common mistakes

  • No wp_next_scheduled() → duplicates
  • Never unscheduling → ghost jobs
  • Low traffic sites → delayed cron
  • Heavy tasks on page load
  • Missing add_action()

Production tip

define( 'DISABLE_WP_CRON', true );
Enter fullscreen mode Exit fullscreen mode

Top comments (0)