HPOS Migration for Large WooCommerce Stores: A Safe Step by Step Plan

How to move a large WooCommerce store to High-Performance Order Storage without downtime: audit, sync, verify, switch, and only then clean up.
Dmytro Koval
CTO at Artilab

A safe HPOS migration on a large WooCommerce store has five stages: audit compatibility, copy orders into the new tables with compatibility mode on, verify the data, switch HPOS to authoritative while sync stays on, and only then turn sync off and clean up. Done this way, both the switch and a rollback are hot operations with no planned downtime. The part that takes time is not the switch itself, it is the audit and the data copy.

Need guidance? Book a 30-minute consultation

What is HPOS and why does it matter for big stores?

High-Performance Order Storage (HPOS) moves orders out of the generic WordPress posts and postmeta tables into dedicated order tables. According to the WooCommerce developer docs, order data lives in four tables:

Table (with your prefix)What it holds
wp_wc_ordersCore order record: status, totals, currency, customer, dates
wp_wc_order_addressesBilling and shipping addresses
wp_wc_order_operational_dataInternal flags and operational fields
wp_wc_orders_metaOrder meta that does not have its own column

HPOS has been enabled by default for new installations since WooCommerce 8.2 (October 2023). Existing stores stay on posts storage until someone migrates them. That is why many older, high-volume stores still run the legacy storage today. They are exactly the stores where a shared postmeta table with millions of rows hurts most.

How long does an HPOS migration take?

The switch itself is instant. The data copy is what takes time, and it depends on order count, meta volume and server capacity.

For scale, WooCommerce's own large store guide reports that syncing a test store with 9 million orders took about a week. Their team disabled sync on read about 6 hours after switching to HPOS, and fully disabled sync after 1 week.

The only reliable estimate for your store is to time the sync on a staging copy of your production database. Plan the calendar around that number, and avoid running the production copy during a sales peak.

Phase 0: What should you audit before touching settings?

Most failed HPOS migrations we see are not data problems. They are code that still reads orders as posts. Audit these four areas first.

Plugins that declare incompatibility

WooCommerce will not let you switch while an active plugin declares itself incompatible. The HPOS documentation says the option to switch is disabled in that case. To see the list, go to WooCommerce > Settings > Advanced > Features and click View and manage, or open wp-admin/plugins.php?plugin_status=incompatible_with_feature&feature_id=custom_order_tables on your site.

A plugin that declares nothing is not proof of compatibility. Check each one with its vendor or in its changelog.

Custom code that reads orders as posts

Search your theme, custom plugins and snippets for order access through WordPress post functions. The HPOS recipe book lists what breaks and the replacements:

Legacy patternHPOS-safe replacement
get_post() on an order IDwc_get_order()
get_post_meta() on orders$order->get_meta()
update_post_meta() / delete_post_meta()$order->update_meta_data() or delete_meta_data(), then $order->save()
WP_Query for shop_orderwc_get_orders() or WC_Order_Query
Direct SQL on wp_posts / wp_postmetawc_get_orders(), or query the HPOS tables
Checking post typeOrderUtil::is_order()

Custom plugins you own should also declare compatibility with FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ), once the code is fixed.

External systems that read the database directly

This is the one teams forget. The large store guide warns that data warehouses, shipping tracking, accounting systems and similar tools may read the posts tables directly. They escape a normal code audit. If your BI dashboards, ERP connector or reporting scripts use SQL against wp_posts, they must be updated before HPOS becomes authoritative.

Database headroom

While compatibility mode is on, order data exists in both storages. Check free disk space and backup size limits with your host before starting the copy.

Phase 1: Test on a local or development copy

Enable HPOS on a development copy with the same plugins, theme and custom code as production, all at their latest versions. The large store guide suggests these minimum tests:

  • Checkout with every payment method.
  • Refunds for those orders.
  • WooCommerce Subscriptions purchases and renewals, if you use it.
  • Your own critical flows: ERP export, fulfilment, invoices, B2B pricing, and so on.

Run the tests twice: once with compatibility mode on and once with it off. Issues that only appear with sync off are real HPOS incompatibilities hiding behind the legacy copy.

Phase 2: Rehearse the migration on staging

Copy the production database to staging. Enable compatibility mode with posts still authoritative, then run the migration from the command line and time it. Use the wp wc hpos commands. Older articles mention wp wc cot, which the HPOS CLI docs now describe as deprecated.

wp wc hpos status
wp wc hpos count_unmigrated
wp wc hpos sync
wp wc hpos verify_data

What each one does:

  • status shows whether HPOS and compatibility mode are on, plus unsynced orders and orders pending cleanup.
  • count_unmigrated tells you how many orders still need to be copied.
  • sync copies orders from the current authoritative storage to the other one, much faster than waiting for background jobs.
  • verify_data compares both storages and reports any order that differs. (The large store guide calls it verify_cot_data.)

Without the CLI, compatibility mode still migrates everything in the background. The enable HPOS guide explains that the scheduled actions wc_schedule_pending_batch_process and wc_run_batch_process process 25 orders at a time. On a store with millions of orders, that is too slow to plan around, which is why the CLI is the right tool.

Once the copy finishes, repeat the Phase 1 tests with sync on, then with sync off. Write down any issues and how you fixed them.

Phase 3: Migrate production step by step

This is the sequence from the WooCommerce large store guide, with the checks we add in practice.

  1. Take a full backup of the database and confirm it restores.
  2. Enable compatibility mode with posts authoritative. In WooCommerce > Settings > Advanced > Features, keep "Use the WordPress posts tables" selected and tick "Enable compatibility mode". New and updated orders now start appearing in the HPOS tables.
  3. Run wp wc hpos sync to copy historical orders. The guide says stopping the sync or interrupting the CLI job is safe if you see errors, and you can resume once they are resolved. Run it in a screen or tmux session so an SSH disconnect does not stop it.
  4. Verify. Run wp wc hpos verify_data and inspect any differing order with wp wc hpos diff followed by the order ID. The backfill command can fix a single order or specific fields.
  5. Switch HPOS to authoritative with sync still on. Select "Use the WooCommerce orders tables" in the same settings screen. Pick a quiet period, but plan to be online afterwards.
  6. Test in production. Place real orders with each payment method, refund one, open a few natural orders and check that all fields are filled. Watch support channels.
  7. Disable sync on read. It is the heavier part of sync. The guide uses this filter in a small custom plugin or mu-plugin:
add_filter( 'woocommerce_hpos_enable_sync_on_read', '__return_false' );
  1. Disable compatibility mode after a stable period (the guide suggests about a week). Untick "Enable compatibility mode".
  2. Keep a fallback. WooCommerce's team still runs wp wc hpos sync periodically after disabling sync, so they can switch back to posts immediately if needed.

The important point: while sync is on, reverting to posts is instant. After sync is off, you can still revert, but the posts tables must first be backfilled with the orders created since.

Phase 4: When should you clean up the legacy data?

Only after weeks of stable operation and a full business cycle: month-end reports, refunds, subscription renewals, tax exports. wp wc hpos cleanup removes order data from the legacy tables once HPOS is on and compatibility mode is off. According to the CLI docs, it does nothing unless you pass an order ID, a range or "all". It refuses orders where the posts copy looks newer, unless you use --force.

Cleanup keeps lightweight placeholder posts of type shop_order_placehold, so storages can still be switched. Take a backup before cleanup. It is the only destructive step in the whole process.

HPOS migration checklist

  • Order count and wp_postmeta size recorded.
  • Incompatible plugins list checked under WooCommerce > Settings > Advanced > Features.
  • Custom code searched for get_post_meta, WP_Query and SQL on orders.
  • External systems (BI, ERP, shipping, accounting) checked for direct database reads.
  • Disk space and backup limits confirmed with the host.
  • Dev copy tested with sync on and off.
  • Staging migration timed with wp wc hpos sync.
  • Data verified with wp wc hpos verify_data.
  • Production: backup, compatibility mode on, sync, verify.
  • HPOS authoritative with sync on, live orders tested.
  • Sync on read off, then sync fully off after a stable period.
  • Cleanup only after a full business cycle and a fresh backup.

Common problems and quick fixes

SymptomLikely causeWhat to do
HPOS option greyed outAn active plugin declares incompatibilityUpdate, replace or remove it, then check the list again
Orders missing fields in adminPlugin writing meta with update_post_meta()Fix the code, then use wp wc hpos backfill for affected orders
Reports or ERP show no new ordersExternal system reads wp_posts directlyUpdate the integration to use the REST API or HPOS tables
verify_data reports differencesOrders changed outside WooCommerce APIs during syncInspect with diff, reconcile with backfill
Cannot disable HPOSOrders still pending syncRun wp wc hpos sync first, as the CLI requires

When to get help

If your store has a large order history, custom order code or external systems reading the database, the audit and rehearsal are where most of the effort goes. Our WooCommerce upgrade service includes HPOS migrations from $600, planned on staging with a fixed scope. If you first want a clear picture of what in your codebase would block HPOS, start with a WooCommerce audit.

Leave a comment

Your email is not published. Comments appear after moderation.

Need WooCommerce developers?

Hire WooCommerce developers who work in European hours, with a 2-week trial.

Hire developers
Featured Story
Can You Sell Inside ChatGPT With WooCommerce? What Works in 2026
  • Platform & Business Strategy

Can You Sell Inside ChatGPT With WooCommerce? What Works in 2026

ChatGPT Instant Checkout came and went. Here is what a…

WooCommerce MCP and Abilities Explained for Store Owners
  • WooCommerce Development

WooCommerce MCP and Abilities Explained for Store Owners

WooCommerce MCP lets AI assistants such as Claude or ChatGPT…

EU AI Act Chatbot Rules for WooCommerce Stores: A Practical Checklist
  • WooCommerce Development

EU AI Act Chatbot Rules for WooCommerce Stores: A Practical Checklist

If your WooCommerce store runs an AI chatbot for EU…

5.0
The team provided professional assistance, overcoming any technical difficulties. They responded quickly, sorted out all my requests, and ensured the stable operation of my site.
Alex Blitshtein
Marketing Manager of Tarya Fintech

Is your store healthy?

Get a free express health check: speed, updates and security flags within 2 business days.

support Get a free health check