Skip to content
WooCommerce HPOS

WooCommerce HPOS: how to switch without breaking your store.

High-Performance Order Storage moves your orders out of the WordPress posts tables and into tables built for orders. New stores have used it by default since WooCommerce 8.2. Older stores have to switch themselves, and the risk is a plugin that still reads orders the old way. Here is how to check what will break, the order we switch in, and how to go back if something does.

First: take a full backup and do it on a quiet day

Switching order storage is reversible, but only while both copies of your orders are kept in step. Before you touch the setting, take a full backup of files and database and make sure you know how to restore it. If your host gives you a staging copy, run the whole plan there first. Pick a quiet hour, not the morning of a sale, and do not switch while a large import or a bulk order edit is running.

What HPOS changes, in plain terms.

For years WooCommerce stored every order as a WordPress post, with the details spread across the same tables as your pages and blog posts. HPOS gives orders their own tables. Most of the time nothing looks different, which is why the problems, when they come, are confusing.

Orders get their own tables

HPOS uses four tables: wc_orders, wc_order_addresses, wc_order_operational_data and wc_orders_meta, each with your site's table prefix in front (wp_ by default). They are designed for orders instead of being shared with every other kind of content.

Default for new stores since 8.2

WooCommerce 8.2, released in October 2023, turned HPOS on for new installations. A store set up before that still uses the old posts storage unless someone switched it.

Existing stores are not moved for you

WooCommerce says existing stores are not migrated automatically. The switch is opt-in, made under WooCommerce, Settings, Advanced, Features. So an updated WooCommerce version alone does not mean your store runs on HPOS.

The Orders screen moves

With HPOS on, the order list lives at admin.php?page=wc-orders instead of the old posts screen. Bookmarks and staff shortcuts to the old order URLs may need updating.

Plugins have to read orders the new way

WooCommerce asks extension developers to load orders with its own functions, such as wc_get_order, and to change order data through the order object and save it, instead of using WordPress post functions or querying the posts tables directly. Code that still reads the posts tables gets old data or none, and what it writes there may never be read.

What it is not

HPOS is not a speed plugin and not a fix for a slow front end. It changes where order data lives in the database. If your shop pages are slow, that is a different problem, see WordPress speed optimization.

Step one: check what will break, before you switch.

WooCommerce has a compatibility check built in, and it catches a lot. But it has a blind spot that most guides leave out. Go through all six points; the last two are the ones that catch stores out.

Go to WooCommerce, Settings, Advanced, Features and find Order data storage. It has two options: WordPress posts storage (legacy) and High-performance order storage (recommended). Whichever is selected is what your store uses now. Below them is a checkbox: Enable compatibility mode (Synchronize orders between High-performance order storage and WordPress posts storage).

If an active plugin is incompatible, the High-performance order storage option is greyed out and you cannot select it. WooCommerce shows a View and manage link to the list. You can also open Plugins with the filter plugin_status=incompatible_with_feature and feature_id=custom_order_tables added to the address. That list is your work list.

A plugin developer declares HPOS support in code. For HPOS, WooCommerce treats a WooCommerce-aware plugin that declares nothing as incompatible, not as fine. So a plugin on the list may work perfectly and simply never have declared it. Others have declared that they do not work. The list does not tell you which is which. The plugin's changelog or support forum usually does.

For each plugin on the list: update it first, because many added HPOS support in later versions. If the newest version is still listed, ask the developer whether HPOS support is planned. If the plugin is no longer maintained, find a maintained replacement or check whether you still need it at all. Deactivated plugins do not block the switch, but do not deactivate one your store depends on just to make the option clickable.

WooCommerce only checks plugins that declare which WooCommerce version they are tested with in their plugin header. Custom code is not checked at all: snippets in your theme's functions.php, a code snippets plugin, a small plugin a developer wrote for you years ago, an integration with your accounting or warehouse system. If any of that reads orders with WordPress post functions, it will not show up on the list, and it will quietly stop working after the switch.

Ask whoever built your custom pieces, or have a developer search the theme and custom plugins for code that reads shop_order posts, uses get_post_meta on order IDs, or queries the posts tables for orders. Then list every system that touches orders: accounting, shipping labels, ERP or warehouse, email marketing, reports, exports. Each one is something to test after the switch.

Step two: the switch-over plan, in the order we use.

The safety net is compatibility mode. While it is on, WooCommerce keeps both storages in step, so you can switch back without losing orders placed in between. WooCommerce itself advises keeping it on for a while after the switch.

Tick Enable compatibility mode and save, while posts storage is still selected. WooCommerce now copies your existing orders into the new tables in the background, in batches run as scheduled actions. The screen shows "Currently syncing orders..." with a count of orders still pending. On a store with many orders this can take a while. Leave it running.

WooCommerce will not let you change the storage while orders are out of sync. You will see "You can switch order data storage only when the posts and orders tables are in sync", with a Sync orders now link. If the count stops moving, check WooCommerce, Status, Scheduled Actions for failed or stuck actions, and make sure WP-Cron or a real server cron is running.

Once the count reaches zero, select High-performance order storage (recommended) and save. Keep compatibility mode ticked. WooCommerce now reads and writes orders in the new tables and copies changes back to the posts tables, so the old storage stays current as your way back.

Place a real test order with each payment method you offer, then refund one. Open, edit and search orders in the admin. Check that order emails arrive. Then go through your list from step one: does the accounting sync still pick up new orders, do shipping labels print, do exports and reports show the latest orders, does the order search find a customer by email.

Give it at least a few normal trading days, including a busy one, with everything that runs weekly or monthly, such as reports or payouts, having run at least once. Watch for any plugin or integration that shows old data or misses new orders.

When you are confident, untick compatibility mode. Your store then writes orders to the HPOS tables only. From here, switching back means syncing again first, so only do this once every integration has been tested. The old order data stays in the posts tables until someone deliberately cleans it up, which is a separate step covered in the FAQ.

Something looks wrong after the switch? Match what you see to the cause.

Problems after an HPOS switch rarely look like errors. They look like missing data. Start from what you see, because each pattern points somewhere different.

An active plugin is on the incompatible list. Open View and manage and work through it as in step one. If both storage options are greyed out, the cause is different: orders are pending sync, and you have to let the sync finish first.

That tool is reading the posts tables. While compatibility mode is on it often still works, because WooCommerce copies orders back, which is exactly why problems tend to appear the day compatibility mode is switched off. Turn compatibility mode back on, then update the tool or ask its developer for an HPOS-ready version.

The plugin is probably writing to the posts tables directly, so its changes never reach the HPOS tables. Since WooCommerce 10.7, sync on read is off by default, so WooCommerce no longer pulls such changes back in when an order is loaded. WooCommerce shows affected stores a one-time notice after the upgrade. A developer can switch the old behaviour back on with the woocommerce_hpos_enable_sync_on_read filter, but WooCommerce says to treat that as temporary. The real fix is in the plugin.

This is the blind spot from step one: custom code the compatibility check never looked at. It usually still reads orders as posts. A developer needs to move it to WooCommerce's order functions.

That may not be HPOS at all. A WooCommerce update can break things through template overrides or extensions that have not kept up, whether or not you switched storage. See WordPress broke after an update for the first steps.

How to go back to posts storage if you need to.

Switching back is supported. The one rule is the same as going forward: both storages have to be in sync before WooCommerce lets you change.

1

Turn compatibility mode on

If you already turned it off, tick it again and save. WooCommerce then copies orders placed since back to the posts tables.

2

Wait for the sync to finish

Watch the pending count go to zero. Do not restore an old database backup to go back: that throws away every order placed since the backup.

3

Select WordPress posts storage

Choose WordPress posts storage (legacy) and save. Keep compatibility mode on, so the HPOS tables stay current for your next attempt.

4

Fix the cause, then try again

Find the plugin or custom code that misbehaved and get it updated. If you cannot find it, see WooCommerce fixes.

Option greyed out, or something broke after the switch? We can sort it.

We find what blocks the switch or what stopped working after it, including custom code the compatibility check does not see. Diagnosis is free, you get a fixed price before we start, and if we cannot fix it, you pay nothing. We back up before we deploy anything and test checkout, the order screens and order emails before we call it done. Quick Fix from €199, excl. VAT. Want updates like this handled every month? See WooCommerce care plans from €129/month.
See our WooCommerce fixes

Questions about switching to HPOS.

Not today. Existing stores are not moved automatically and posts storage still works. But it is called legacy in the settings for a reason, and new extensions are built and tested on HPOS first. Switching on your own schedule, with a plan, beats being pushed into it later by a plugin that needs it.
Look at Order data storage under WooCommerce, Settings, Advanced, Features. If High-performance order storage is selected, you are on HPOS. Another quick sign: the order list address contains page=wc-orders.
Not if you follow the plan: sync first, switch with compatibility mode on, keep it on while you test. WooCommerce does not allow the change while orders are pending sync. The real risk is not lost orders but a plugin or integration that stops seeing them.
There is a WP-CLI flag, --ignore-plugin-compatibility, that enables HPOS despite the check. Only use it after you have confirmed with the developer, or by testing on a staging copy, that the plugin really works with HPOS. Otherwise you are switching off the one warning WooCommerce gives you.
Yes, through WP-CLI. wp wc hpos status shows the current state, wp wc hpos compatibility-info lists plugin compatibility, wp wc hpos count_unmigrated and wp wc hpos sync handle the sync, wp wc hpos verify_data compares both storages, and wp wc hpos enable --with-sync switches with compatibility mode on. Useful on large stores where the background sync is slow.
It stays there after you turn compatibility mode off. WP-CLI has a wp wc hpos cleanup command that deletes the leftover post data of migrated orders. It only runs with HPOS active and compatibility mode off, it cannot be undone except from a backup, and it refuses an order whose posts copy looks newer than its HPOS copy unless you add --force. Leave it alone until you are sure you will not need to go back, and take a backup first.
Yes. After a free diagnosis you get a fixed price in writing before we start. Fixes start at our Quick Fix price, from €199 excl. VAT, and if we cannot fix it, you pay nothing. See WooCommerce fixes. If you want updates like this handled every month, see WooCommerce care plans from €129/month.

Sources

Last checked 12 November 2026, against WooCommerce 11.3. Labels and defaults change between versions, so check the current documentation before you rely on a detail.

WooCommerce: High-Performance Order Storage: opt-in for existing stores, the incompatible extensions list, keeping compatibility mode on, switching back.
WooCommerce developer docs: HPOS and How to enable HPOS: default since 8.2, the four tables, the background sync.
WooCommerce developer docs: HPOS recipe book: how plugins declare compatibility and should read orders.
WooCommerce developer docs: wc hpos commands: the WP-CLI commands and flags.
WooCommerce developer blog: sync on read off by default in 10.7: the change, the notice and the filter.
WooCommerce source: CustomOrdersTableController and PluginUtil: setting labels, sync messages, which plugins are checked and why undeclared ones count as incompatible.
WooCommerce source: CLIRunner and PageController: when cleanup is allowed, and the wc-orders screen.

Stuck on the switch?

We will find what blocks HPOS, or what broke after it.

Free diagnosis, a fixed price before we start, and no fix, no fee. Quick Fix from €199. Backup before we deploy, checkout and order tests before we call it done.

Chat on WhatsApp