--- title: Put a time limit on WooCommerce On Hold orders description: On Hold orders hold reserved stock indefinitely. The built-in Pending Payment timer does not cover them. A small plugin cancels them on a configurable schedule. source: https://steem.dev/blog/woocommerce-on-hold-orders-time-limit published: 2026-11-12 updated: 2026-11-12 site: Steem — AI WordPress plugin generator --- # Put a time limit on WooCommerce On Hold orders Bank transfer and cheque payment in WooCommerce create orders with On Hold status. The gateway fires, stock is reserved, the customer receives payment instructions. If the payment never arrives, the order sits in On Hold for days or weeks, with the stock still counted as unavailable to everyone else. WooCommerce has a built-in control for this under Settings > Products > Inventory: 'Hold stock (minutes)' cancels Pending Payment orders after a timer. The documentation is clear that this applies only to Pending Payment, not On Hold. The two statuses exist for a reason: Pending Payment is mid-checkout, On Hold is post-commitment. That distinction is exactly why a site-wide minute-level timer does not cover both, and why a separate scheduled check for On Hold orders is needed. ## What one build covers - Scheduled cancellation of On Hold orders past a configurable age in hours - Settings field under WooCommerce > Settings > Advanced for the threshold - Automatic stock restoration handled by WooCommerce on status change - Order note marking each cancellation as automatic with the hours elapsed ## What it does not cover - Pending Payment orders: use the built-in Hold stock setting for those - Pre-cancellation warning email to the customer before the order is cancelled - Orders in any status other than On Hold - Deposits or partial payment workflows where On Hold is used for the full payment duration ## The prompt ```text Build a WordPress plugin that automatically cancels WooCommerce orders in On Hold status after a configurable number of hours. Add a settings field labeled 'Cancel On Hold orders after (hours)' with a default of 48 under WooCommerce > Settings > Advanced, stored in wp_options. Register a WP-Cron event that runs every six hours. In the callback, use wc_get_orders() to find orders with status on-hold that were last updated more than the configured number of hours ago. For each matching order, call update_status('cancelled') and add an order note recording how many hours the order had been On Hold and that the cancellation was automatic. Log each cancellation via wc_get_logger() with the order ID and the hours elapsed. ``` ## What Pending Payment and On Hold both do to your stock When WooCommerce creates an order, it calls wc_reduce_stock_levels() regardless of whether the status is Pending Payment or On Hold. Both reduce the available stock count immediately. Pending Payment orders get their stock back if the built-in timer fires and the order is cancelled. On Hold orders do not, unless someone manually cancels them or the payment is confirmed. For limited-stock items, a single On Hold order that sits for three days is effectively a sale that never happened, blocking real buyers for the entire period. ## Why 48 hours works as a starting point and 60 minutes does not The built-in Pending Payment timer exists because Pending Payment is the status during the checkout redirect. If the customer's browser closes before returning from the payment gateway, the order should clear quickly so the stock is not tied up overnight. Sixty minutes is a reasonable window for that. On Hold is different. The customer has already committed, received payment instructions, and is expected to follow through. Bank transfers take one to three business days in most countries. Clearing On Hold orders in an hour would cancel legitimate payments before they have time to arrive. A 48-hour default gives enough time for a same-day transfer to clear while preventing orders from holding stock over a long weekend. Stores that accept international bank transfers often extend this to 72 or 120 hours. ## The cancellation chain and what it sets off When the plugin calls $order->update_status('cancelled'), WooCommerce fires woocommerce_order_status_changed and then woocommerce_cancelled_order. Stock restoration is handled inside that second hook: WooCommerce calls wc_increase_stock_levels() automatically, so no extra code is needed to free the reserved units. The standard 'Order Cancelled' email goes to the customer unless you have disabled it under WooCommerce > Settings > Emails. For stores that rely on bank transfer, reviewing that email's wording before the plugin runs its first cycle is worth doing, so customers receive a message that explains the payment window closed rather than one that reads like a system error. An order note records each cancellation as automatic, with the hours elapsed. Manual cancellations and automatic ones are otherwise identical in the order timeline, and the distinction matters when a customer disputes a cancellation or a payment arrives the day after the order was cleared. ## Questions ### My payment gateway puts orders On Hold during a fraud review. Will those be cancelled too? Yes, if they remain On Hold past the configured threshold. Gateways that hold orders for internal review typically resolve within a few hours. Setting the threshold to 24 hours or more should give the gateway time to finish its review in most cases. If yours routinely holds orders for longer, raise the threshold to match. --- Source: https://steem.dev/blog/woocommerce-on-hold-orders-time-limit Build this plugin: https://steem.dev/app