QasimCode.
ServicesPortfolioBlogContactHire Me
Home/Blog/WooCommerce HPOS Custom Queries Breaking: The Fix
WooCommerceWordPressHPOS

WooCommerce HPOS Custom Queries Breaking: The Fix

WooCommerce HPOS breaks custom order queries using WP_Query or postmeta. Here's the exact fix with working code for WooCommerce 8.7+ stores.

MQ

Muhammad Qasim

Senior Full Stack Developer

April 17, 2026
5 min read

Problem

A client pinged me last week: after enabling High-Performance Order Storage (HPOS) on their WooCommerce 8.7 store, their custom order reports went blank. The dashboard widgets, the CSV export, the Slack notifications — nothing pulled orders anymore. Fatal errors in the logs:

PHP Notice: Function WC_Order was called incorrectly.
Order properties should not be accessed directly.

And the bigger one:

Uncaught Error: Call to undefined method WC_Order::get_post_meta()

If you're reading this, you've probably just flipped the HPOS switch under WooCommerce → Settings → Advanced → Features and half your custom code exploded. Here's why, and how I fixed it.

Why It Happens

Before HPOS, WooCommerce stored orders as shop_order posts in wp_posts, with order data in wp_postmeta. That's how it worked for a decade, so every plugin, snippet, and custom report written for WooCommerce queried those tables directly.

HPOS moves order data into dedicated tables: wp_wc_orders, wp_wc_order_addresses, wp_wc_order_operational_data, and wp_wc_orders_meta. When you enable HPOS, the old postmeta rows are no longer the source of truth — they're either empty or stale depending on your sync setting.

So any code that does this is now broken:

// Broken on HPOS — returns nothing
$orders = new WP_Query([
    'post_type'   => 'shop_order',
    'post_status' => 'wc-completed',
    'meta_query'  => [
        [
            'key'   => '_billing_email',
            'value' => 'customer@example.com',
        ],
    ],
]);

WP_Query hits wp_posts. There are no orders there under HPOS. The query returns an empty set, your report goes blank, and your export silently ships a zero-row CSV.

The Fix

WooCommerce provides wc_get_orders() as the HPOS-safe equivalent. It abstracts the storage layer, so it works whether HPOS is on or off. Rewrite the query like this:

$orders = wc_get_orders([
    'status'         => 'completed',
    'billing_email'  => 'customer@example.com',
    'limit'          => -1,
    'return'         => 'objects',
]);

foreach ($orders as $order) {
    $total    = $order->get_total();
    $email    = $order->get_billing_email();
    $order_id = $order->get_id();
    // do stuff
}

A few gotchas I hit on the client site:

1. Don't access postmeta directly. If your code calls get_post_meta($order_id, '_billing_total', true), swap it for the order method:

// Before (breaks on HPOS)
$total = get_post_meta($order_id, '_billing_total', true);

// After (works on both)
$order = wc_get_order($order_id);
$total = $order->get_total();

2. Custom meta still works, but use the order API. If you've been storing custom fields like _qasim_gift_message on orders, read them via $order->get_meta():

$gift_message = $order->get_meta('_qasim_gift_message');
$order->update_meta_data('_qasim_gift_message', 'Happy birthday');
$order->save();

3. Complex SQL needs the new tables. If you had a raw $wpdb query joining wp_posts and wp_postmeta, you need to rewrite it against wp_wc_orders and wp_wc_orders_meta. For most cases, though, wc_get_orders() with a meta_query arg covers you:

$orders = wc_get_orders([
    'status'     => 'processing',
    'limit'      => 100,
    'meta_query' => [
        [
            'key'     => '_qasim_gift_message',
            'compare' => 'EXISTS',
        ],
    ],
]);

4. Check compatibility before enabling. WooCommerce shows an incompatible plugin warning on the HPOS settings page. Don't ignore it. I had a client whose affiliate plugin hadn't updated for HPOS, and enabling it dropped 3 months of referral data from the reports. Run this in the admin to audit:

WooCommerce → Status → Logs → fatal-errors

And the CLI audit if you prefer:

wp wc hpos verify_cot_data --verbose

5. Turn on compatibility mode during the rollout. Under Advanced → Features, set data sync to Keep the posts table and orders tables synchronized. That way, if a plugin still reads from postmeta, it keeps working while you fix the calling code. Only turn sync off once every query uses the order API.

One More Thing — Scheduled Actions

If you use Action Scheduler jobs that grab orders (abandoned cart emails, subscription renewals, sync to an ERP), double-check the callback. Most of mine were built with get_posts('shop_order'). Every one of them broke silently.

Here's a safer pattern I now use as the default:

add_action('qasim_daily_order_sync', function () {
    $orders = wc_get_orders([
        'status'       => ['processing', 'completed'],
        'date_created' => '>' . (time() - DAY_IN_SECONDS),
        'limit'        => -1,
    ]);

    foreach ($orders as $order) {
        qasim_sync_order_to_erp($order);
    }
});

date_created accepts a timestamp prefix (>, <, or a range with ...). That's not documented well anywhere — the official HPOS developer guide is the closest thing.

For a deeper look at making WooCommerce stores fast at the infrastructure level, my WordPress performance optimization guide covers the caching and database work I pair with HPOS migrations.

Need a Hand With Your HPOS Migration?

I've migrated production WooCommerce stores to HPOS without losing a single order or report. If your store is stuck in compatibility mode or your custom plugin is throwing errors, book a quick audit on my services page and I'll tell you exactly what needs to change.

Need Help With This?

I offer professional web development services — WordPress, React/Next.js, performance optimization, and technical SEO.

Get in Touch
All Posts

About the Author

MQ

Muhammad Qasim

Senior Full Stack Developer with 5+ years experience in React, Next.js, and WordPress. Based in Pakistan, working globally.

Need a Web Developer?

I build WordPress sites, React apps, and optimize web performance.

View Services

Related Posts

  • WooCommerce Checkout Block Payment Methods Missing: Fix5 min read
  • WordPress Performance Optimization: How I Cut Load Times by 60%3 min read
  • Next.js vs WordPress: Which Should You Use in 2026?4 min read

QasimCode.

Senior Full Stack Developer building web solutions that deliver measurable growth.

hello@qasimcode.com

Services

  • WordPress Dev
  • React / Next.js
  • Performance
  • E-commerce
  • Technical SEO

Resources

  • Blog
  • Portfolio

Company

  • About
  • Contact
  • LinkedIn

© 2026 Muhammad Qasim. All rights reserved.

Pakistan — Remote worldwide