We typed a customer name into the order search of a WooCommerce store with 400,000 orders. Vibery Sites answered in 0.49 seconds the first time, and in about 90 milliseconds on repeats. WooCommerce's own search, on the same store, took 7.6 seconds.
Those are server-side times: the first request is the cold one, and the repeats are the 95th percentile of five. From a browser across the world, the first search took 0.85 seconds. All of it is in this post, along with the number that matters more: our first run, which was much worse.
The store nobody wants to own
Most WooCommerce stores never reach 10,000 orders. We built one with 400,000 anyway, because that is where an admin breaks first: 30,002 products plus 49,352 variations, 90,002 customers, 1,000,210 order lines, 3,001 coupons, 30,001 reviews. A 3.5 GB database on a real hosted WordPress 7.0.7 with WooCommerce 11.2.1 and high-performance order storage turned on.
We did not stop at one store. A small shop (200 products, 1,500 orders), a growing one (3,000 products, 30,000 orders) and a catalog-heavy one (100,002 products and 165,001 variations, only 20,000 orders) came with it. The seed is deterministic and each store is a snapshot we can restore. The 400k store comes back in about five minutes. So this is not a one-off: we run the same test again after every release, and keep the history.
It all ran on one shared 8-core server that also hosts other sites. The load average stayed between 2 and 4 during the sync. We left it messy on purpose. A clean lab would have flattered us.
First, get the data out
Vibery Sites keeps a searchable copy of your orders, products and customers, and answers from the copy. Your WordPress site stays the source of truth; every change you save goes back to it.

Building that copy is the first test. WooCommerce's standard API hands out orders at 13 to 20 a second. At that speed, 400,000 orders is between five and a half and eight and a half hours of hammering your shop. We wrote a bulk path into our plugin instead. It synced the whole 400,000-order store in 82 minutes while the server kept serving other sites, newest orders first, so the console is usable within minutes. The catalog-heavy store, 265,000 products and variations, took 23 minutes.
Eighty-two minutes is not a number to brag about. It is a number we can improve, and one run of ours showed why: after we restored a backup, the plugin silently rolled back to an older version, and the same sync took three hours. We found it in the logs, fixed the test runner, and left the three-hour result out of our headline numbers. It is in the list of things we do not yet know, below.
2026-10-14T09:46:54Z walk orders: DONE 4149s 408201 rows
2026-10-14T09:53:54Z walk customers: DONE 420s 90001 rows
2026-10-14T09:55:39Z walk products: DONE 104s 30002 rows
2026-10-14T09:58:44Z walk products:variation: DONE 185s 49352 rows
2026-10-14T09:59:08Z walk coupons: DONE 23s 3164 rowsFrom the benchmark box's own log: one full copy of the store. The five times add up to 4,881 seconds, about 81 minutes.
The first run failed five of our own targets
With the copy in place, we timed everything a store owner does. Opening the order list: 994 ms. Filtering by status: 550 ms. Searching: 1,386 ms. Jumping to page 150: 1,342 ms. The customer segment counts: 1,257 ms. Five of our own speed targets missed, on the one store we had built to find out.
Then we sent a hundred requests at it, twenty at a time. The slowest 5% waited 13 seconds.
The cause was not exotic. We asked the database for "newest first" in a way its own index could not answer. So every time someone opened the orders page, it sorted all 400,000 orders to hand back twenty. The fix was a small change in how the ordering is written, so the existing index could answer it. Same store, same server, same day:
Each number in the tables is the 95th percentile of five repeats; the first, cold request is slower (489 ms for the search, 86 ms for the first page of orders).
p95, 400,000 orders | Before | After |
|---|---|---|
Orders, first page | 994 ms | 37 ms |
Orders filtered by status | 550 ms | 36 ms |
Orders search | 1,386 ms | 91 ms |
Orders, page 150 | 1,342 ms | 54 ms |
Customer segment counts | 1,257 ms | 45 ms |
100 requests, 20 at a time | 13 s | 1.4 s |
After the fix, none of our targets failed. All 100 requests came back fine.

v42 "slo_breaches": [
"box.orders_p20.p95 993.7ms > 500ms",
"box.orders_status.p95 550.3ms > 500ms",
"box.orders_q.p95 1385.7ms > 1000ms",
"box.orders_deep.p95 1341.5ms > 1000ms",
"box.customers_counts.p95 1256.7ms > 600ms"
]
v43 "slo_breaches": []The same field in the result file of the first run and of the run after the fix.
[box] p95 ms A -> B
customers_counts 1256.7 -> 44.9 (-96%) improved
orders_deep 1341.5 -> 54.2 (-96%) improved
orders_p20 993.7 -> 36.5 (-96%) improved
orders_q 1385.7 -> 90.7 (-93%) improved
wc_orders_q 11086.2 -> 7608.7 (-31%) improvedOutput of our compare script, first run against the run after the fix, five lines of it. The last line is WooCommerce's own REST search, which we did not change.
Where it is not faster
We compared against WooCommerce's own REST API on the same store, same moment:
p95 | WooCommerce REST | Vibery Sites |
|---|---|---|
Orders, first page | 837 ms | 37 ms |
Orders search | 7,609 ms | 91 ms |
Customers, first page | 1,301 ms | 97 ms |
Products, first page | 164 ms | 145 ms |

Products are about even. A plain WooCommerce product list is already quick, and we will not pretend otherwise. What changes is orders, search and counts, the parts that grow with your history.
Doing things to a big store
Speed means little if bulk actions scare you. Every bulk change in the console shows a preview first and keeps a restore point you can undo. We ran 158 write checks on the 400,000-order store and the same 158 on the catalog-heavy one: coupons, sales, reviews, customers, orders, settings, bulk edits, import. All 316 passed.
Writes are slower, because they go through WooCommerce itself and keep an undo copy. Editing 500 products took 16.8 seconds, and undoing it 15.3. A CSV export of 39,467 products took about ten minutes. We have not worked on this yet.
When a change happens on the site, the console sees it about two seconds later. We measured 1.9 to 2.1 seconds.
What we still do not know
All of this is one server. Sites that connect to us from somewhere else, not hosted by us, were not run at this scale. We have not run a store with four million orders, and we do not know where this design starts to bend. The first sync depends on how busy your host is: the same 400,000 orders took 82 minutes on one run and three hours on another.
How we build this
We do not guess how a store behaves at scale. We build it, break it, and write the numbers down.
The method is plain. We seed a store from a fixed recipe, so the same 400,000 orders exist every time. We snapshot it, so we can put it back in five minutes. We run the same set of timings against it and label every run with the version of the product that produced it. In one day we measured three versions, v41, v42 and v43, on the same data. The first two runs gave us the baseline and showed where the time went; the third, after the ordering fix, is the one with the 37 ms.
Two rules keep us honest. The test only ever touches its own bench site, with a key that can reach nothing else and is revoked when the run ends. And a bad number goes in the report next to the good ones, because a result we hide is a result we cannot fix.
That is also why we test the risky paths, not only the fast ones: on a big store a wrong bulk change is expensive, so every one has a preview and an undo, and we ran all 316 write checks against them. We would rather find the 7.6-second search ourselves, on our own server, than have you find it on a Monday morning with orders waiting.
We will keep running it, on a schedule, as the product changes. When a number gets worse, you will see it here.
A store with 400,000 orders is rare. But if you have 40,000 and it already feels slow, this is the gap that will widen. What would you need to see before you moved the admin off your shop's own database?




No comments yet