
Deep Dive into WooCommerce HPOS (High-Performance Order Storage)
WooCommerce HPOS (High-Performance Order Storage) is a major enhancement designed to improve the performance of order management in WooCommerce, especially for stores with a high volume of orders. In this blog post, we’ll explore what HPOS is, how it works, its database structure, performance improvements, and how developers can adapt their plugins and code to work seamlessly with HPOS.
Why HPOS?
WooCommerce originally stored orders as a custom post type (shop_order
), using the standard WordPress wp_posts
and wp_postmeta
tables. As WooCommerce evolved and stores grew larger, this architecture became a performance bottleneck due to the inefficiency of querying large volumes of postmeta data.
To resolve this, the WooCommerce team introduced HPOS, a new way of storing order data using dedicated custom tables. As of WooCommerce version 8.2, HPOS is enabled by default for all new stores.
What is HPOS?
HPOS stands for High-Performance Order Storage. Instead of storing orders as custom post types, WooCommerce now uses a set of purpose-built database tables to store order-related information. This significantly improves performance by reducing the need to query generic WordPress tables.
Key HPOS Tables
HPOS introduces several new tables:
wp_wc_orders
: Stores core order information.wp_wc_order_addresses
: Stores billing and shipping addresses.wp_wc_order_operational_data
: Stores operational data like order status that changes frequently.wp_wc_orders_meta
(optional): Similar towp_postmeta
, this table can be used by third-party plugins to store additional metadata.
Performance Comparison
Let’s look at a real-world SQL example to highlight the performance improvements:
Classic CPT-Based Query
SELECT wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta AS country ON wp_posts.ID = country.post_id AND meta_key = '_billing_country'
WHERE wp_posts.post_type = 'shop_order'
AND country.meta_value = 'DK'
HPOS-Based Query
SELECT wp_wc_orders.id
FROM wp_wc_orders
INNER JOIN wp_wc_order_addresses AS address ON address.order_id = wp_wc_orders.id AND address.address_type = 'billing'
WHERE address.country = 'DK'
For a store with around 5,000 orders, the HPOS query can be up to 4 times faster, especially because it avoids the bloated wp_postmeta
table.
Enabling HPOS
To enable HPOS:
- Go to WooCommerce > Settings > Advanced > Features.
- Toggle High-Performance Order Storage to enable it.
Things to Note
- Enabled by default in WooCommerce 8.2+ for new stores.
- You cannot enable HPOS if incompatible plugins are active.
- Pending orders may need to be synchronized before switching.
- Compatibility mode allows HPOS and CPT-based storage to coexist (not recommended for performance, but good for plugin compatibility).
Making Your Plugin Compatible
If your plugin uses WP_Query
, get_post_meta()
, or other WordPress core functions to handle orders, it may not work correctly with HPOS.
The best practice is to use WooCommerce’s CRUD-based methods. If you already use WC_Order
, you may not need to change anything.
Examples
Fetching an Order:
$order = wc_get_order( $order_id );
$order_status = $order->get_status();
Querying Orders:
$query = new WC_Order_Query( array( 'limit' => 10 ) );
$orders = $query->get_orders();
Checking Order Type:
use Automattic\WooCommerce\Utilities\OrderUtil;
if( 'shop_order' === OrderUtil::get_order_type( $post_id ) ) {
// Do something
}
Order Placeholders
Each HPOS order also creates a placeholder post (shop_order_placehold
) in wp_posts
. These placeholders exist for backward compatibility but contain minimal data.
Detecting HPOS Programmatically
To check whether HPOS is enabled:
use Automattic\WooCommerce\Utilities\OrderUtil;
if( OrderUtil::custom_orders_table_usage_is_enabled() ) {
// HPOS is enabled
}
Declaring Plugin Compatibility
To prevent WooCommerce from allowing HPOS with an incompatible plugin, you can declare this:
add_action( 'before_woocommerce_init', function() {
if( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'custom_order_tables',
__FILE__,
false // Set to true if compatible
);
}
});
Screen ID Changes
Since orders are no longer posts, the screen ID for the order list has changed from edit-shop_order
to woocommerce_page_wc-orders
.
Example: Show Admin Notice on Order Page
add_action( 'admin_notices', function() {
$screen = get_current_screen();
if( 'woocommerce_page_wc-orders' === $screen->id ) {
echo '<div class="notice notice-info"><p>Hey there</p></div>';
}
});
Example: Add Custom Column to Order List
add_filter( 'manage_woocommerce_page_wc-orders_columns', function( $columns ) {
$columns['misha_column'] = 'Info from Misha';
return $columns;
});
Conclusion
WooCommerce HPOS is a powerful update that addresses long-standing performance issues in order management. For developers and store owners, understanding the new data structure and switching to WooCommerce’s official methods will unlock better performance, especially at scale. While it may take some effort to migrate or update existing code, the benefits in speed and scalability are well worth it.
Comments are closed.