Action Hook since 2.9.0

wp_scheduled_delete

Fires daily via WP-Cron, right before old trashed posts are purged

Description

wp_scheduled_delete runs once a day as a scheduled WP-Cron event, immediately before WordPress permanently deletes posts that have sat in Trash longer than EMPTY_TRASH_DAYS.

When it runs

Background, triggered by WP-Cron's wp_scheduled_delete cron event — not tied to any front-end or admin request directly.

Signature

do_action( 'wp_scheduled_delete' );

Examples

Basic

add_action( 'wp_scheduled_delete', function() {
    error_log( 'Trash cleanup cron run started.' );
} );

Log every time the trash-cleanup cron event fires.

Real case

add_action( 'wp_scheduled_delete', function() {
    // Run a custom cleanup of orphaned postmeta alongside core's trash purge.
    global $wpdb;
    $wpdb->query( "DELETE pm FROM {$wpdb->postmeta} pm LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE p.ID IS NULL" );
} );

Piggyback custom database cleanup onto WordPress's existing daily cron slot.

Edge case

add_action( 'wp_scheduled_delete', function() {
    // Only fires if WP-Cron itself is running — a site with
    // DISABLE_WP_CRON set and no real system cron never triggers this.
} );

On a site with WP-Cron disabled and no server cron configured, this event simply never fires.

Common Use Cases

  • Piggyback custom database cleanup on the daily cron cycle
  • Log or monitor trash-purge activity
  • Audit how much content is being auto-deleted
  • Trigger a backup before old content is purged

Common mistakes

  • Assuming this runs at a precise time — WP-Cron is request-triggered, so on low-traffic sites it can be delayed well past its scheduled time
  • Not accounting for DISABLE_WP_CRON — if the site relies on a real system cron hitting wp-cron.php, this event depends on that being configured correctly

Related hooks

FAQ

How often does wp_scheduled_delete run?

Once daily, as one of WordPress's built-in scheduled events.

Why didn’t this fire at exactly midnight?

WP-Cron is pseudo-cron — it only checks for due events on incoming site requests, so timing depends on traffic unless a real system cron drives it.

Source: wp-includes/cron.php

Group wizard

One session: this hook, then each related_hooks entry. Walk it and tell us what to change.

wp_scheduled_delete → delete_attachment → cron_request

functions.php — wp_scheduled_delete
functions.php
PHP wp_scheduled_delete · Hook 1 of 3 · Step 1 of 6

Practice the wp_scheduled_delete WordPress action hook in our interactive sandbox — a VS Code-style editor with a step-by-step wp_scheduled_delete tutorial, add_action exercises, and instant feedback. No local WordPress install required.