How to automatically clean up pending and failed WooCommerce orders

WooCommerce stores every order attempt—including incomplete and failed transactions—which can quickly clutter your database and admin dashboard if left unmanaged.

If you’ve noticed a growing number of “Pending payment” or “Failed” orders, you’re not alone. These often come from abandoned checkouts, payment interruptions, or user errors. Without cleanup, they can impact reporting accuracy and backend usability.

This guide walks through how to automatically manage and clean up these order statuses in WooCommerce.

Issue Background

A WooCommerce store was accumulating a large number of:

  • Pending payment orders (abandoned or incomplete checkouts)
  • Failed payment orders (unsuccessful transactions)

These orders were:

  • Not being automatically deleted
  • Cluttering the admin interface
  • Making order management and reporting more difficult

The desired behavior was:

  • Remove pending payment orders after 24 hours
  • Retain failed orders for a limited time (e.g., 7 days) for reference

Diagnosis

WooCommerce does not automatically delete orders by default.

Key findings:

  • Pending payment orders remain indefinitely unless manually removed or automated
  • Failed orders are also retained permanently
  • WooCommerce cron jobs handle some cleanup, but not order deletion
  • No native setting exists to define retention periods for these statuses

Resolution Steps

1. Identify target order statuses

WooCommerce uses specific order statuses:

  • pending → created but not paid
  • failed → payment attempt unsuccessful

2. Create a scheduled cleanup function

You can use WordPress cron (wp_cron) to automate deletion.

add_action('init', function() {
    if (!wp_next_scheduled('cleanup_old_orders')) {
        wp_schedule_event(time(), 'hourly', 'cleanup_old_orders');
    }
});

add_action('cleanup_old_orders', function() {

    $args = [
        'limit' => -1,
        'status' => ['pending', 'failed'],
    ];

    $orders = wc_get_orders($args);

    foreach ($orders as $order) {
        $created = strtotime($order->get_date_created());
        $now = time();

        // Delete pending orders older than 24 hours
        if ($order->get_status() === 'pending' && ($now - $created) > 86400) {
            wp_delete_post($order->get_id(), true);
        }

        // Delete failed orders older than 7 days
        if ($order->get_status() === 'failed' && ($now - $created) > 604800) {
            wp_delete_post($order->get_id(), true);
        }
    }
});

3. Adjust retention timing as needed

  • 86400 seconds = 24 hours
  • 604800 seconds = 7 days

Adjust these values depending on your store’s needs.

4. Test in a staging environment

Before deploying:

  • Verify orders are deleted correctly
  • Confirm no valid orders are affected
  • Monitor cron execution using tools like WP Crontrol

5. Consider plugin-based alternatives

If you prefer a no-code solution, some plugins offer similar functionality, but custom code provides more control.

Final Outcome

  • Pending payment orders are removed after 24 hours
  • Failed orders are retained briefly, then cleaned up
  • Admin dashboard is significantly cleaner
  • Reporting accuracy improves
  • Database size is reduced over time

This approach keeps WooCommerce running efficiently without losing access to short-term transaction data when needed.

Need help optimizing WooCommerce performance?

Managing order data, automating cleanup, and customizing WooCommerce behavior can significantly improve performance and usability.

If your store is dealing with cluttered orders or complex workflows, Freshy can help implement tailored solutions.

Contact Freshy