# Old Revisions Cleanup Tool

> Adds Tools > Clean Up Revisions, which shows how many post revisions your database holds and deletes revisions older than a chosen number of days after you confirm, always keeping the newest few per post.

- Type: PHP
- Runs: Admin only
- Category: [Performance](https://wpide.com/library/category/performance/)
- Tags: database, revisions, cleanup
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/perf-revisions-cleanup-tool/

## Code

```php
// Revisions newer than this are kept, and the newest N per post are always kept.
$wpide_rev_days = 30;
$wpide_rev_keep = 3;

add_action( 'admin_menu', function () use ( $wpide_rev_days, $wpide_rev_keep ) {
    add_management_page( 'Clean Up Revisions', 'Clean Up Revisions', 'manage_options', 'wpide-revisions-cleanup', function () use ( $wpide_rev_days, $wpide_rev_keep ) {
        global $wpdb;

        $cutoff = gmdate( 'Y-m-d H:i:s', time() - $wpide_rev_days * DAY_IN_SECONDS );

        if ( isset( $_POST['wpide_clean_revisions'] ) && check_admin_referer( 'wpide_clean_revisions' ) && current_user_can( 'manage_options' ) ) {
            // Revisions that are old enough and not among the newest N of their post.
            $ids = $wpdb->get_col( $wpdb->prepare(
                "SELECT r.ID FROM {$wpdb->posts} r
                 WHERE r.post_type = 'revision' AND r.post_date_gmt < %s
                 AND ( SELECT COUNT(*) FROM {$wpdb->posts} n WHERE n.post_parent = r.post_parent AND n.post_type = 'revision' AND n.post_date_gmt > r.post_date_gmt ) >= %d
                 LIMIT 500",
                $cutoff,
                $wpide_rev_keep
            ) );
            foreach ( $ids as $id ) {
                wp_delete_post_revision( (int) $id );
            }
            printf( '<div class="notice notice-success"><p>%s</p></div>', esc_html( sprintf( 'Deleted %d revision(s).', count( $ids ) ) ) );
        }

        $total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = 'revision'" );
        $old   = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_date_gmt < %s", $cutoff ) );

        echo '<div class="wrap"><h1>Clean Up Revisions</h1>';
        printf( '<p>%s</p>', esc_html( sprintf( 'Your database holds %1$s revision(s); %2$s are older than %3$d days. The newest %4$d revisions of each post are always kept.', number_format_i18n( $total ), number_format_i18n( $old ), $wpide_rev_days, $wpide_rev_keep ) ) );
        echo '<form method="post" onsubmit="return confirm(\'Permanently delete old revisions? Make sure you have a backup.\');">';
        wp_nonce_field( 'wpide_clean_revisions' );
        submit_button( 'Delete old revisions (up to 500)', 'primary', 'wpide_clean_revisions', true, $old ? array() : array( 'disabled' => 'disabled' ) );
        echo '</form></div>';
    } );
} );
```

## Notes

Back up your database first; it works in batches of 500 so it never times out, so click again until the count reaches zero.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Old Revisions Cleanup Tool" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
