Someone read my March post about MariaDB 10.11 vs 11.4 and asked a fair question: they’re on 10.6.27, they never noticed any difference moving to 10.11, and a client wants to update. Is it worth it?
Short answer for that specific hop: no, you won’t feel it. But 10.6 hit end of life on July 6, 2026, so the update is worth doing anyway, and if you’re touching it at all you may as well go further than 10.11.
That question also made me realise my March post is out of date. My own host’s panel now offers 12.3.2 by default, with 13.0 sitting there as a release candidate. So I re-ran everything across six versions.
What I tested
MariaDB 10.6.28, 10.11.18, 11.4.12, 11.8.8, 12.3.2 and 13.0.1-RC. Same WordPress 7.1, same PHP 8.4.24, same WooCommerce 11.0.1, same data every time.
The dataset: 1,000 posts, 200 WooCommerce products, 5,000 comments, 101 users, 7,798 postmeta rows.
I rebuilt the test rig for this one. Three things I did differently to March, and the third one matters:
- One database at a time. In March I ran both versions side by side on the same machine, which means they were fighting for CPU. This time each version gets the box to itself.
- Identical data, not identically seeded data. I build the dataset once on 10.6, dump it, and import that same dump into every version. In March I ran the seeder twice, which gets you close but not identical.
- Two full passes, second one in reverse order. 10.6 first then 13.0, then 13.0 first then 10.6. Anything that doesn’t show up in both passes is noise, and I’ll come back to how much noise there actually is.
Stock config throughout. No tuning, no buffer pool changes. I want to know what upgrading gives you, not what tuning gives you.
10.6 to 10.11: nothing
Every query, both passes, in milliseconds:
| Query | 10.6 | 10.11 | Change |
|---|---|---|---|
| Autoloaded options | 0.072 | 0.073 | +2.8% |
| Single post + meta | 0.158 | 0.161 | +1.9% |
| Archive page (posts+meta+tax) | 3.562 | 3.809 | +6.9% |
| Correlated subquery | 1.352 | 1.380 | +2.0% |
| LIKE search | 0.101 | 0.103 | +2.5% |
| Aggregate (posts per category) | 0.282 | 0.299 | +6.0% |
| UPDATE with subquery | 7.521 | 8.764 | +16.5% |
| WooCommerce product listing | 0.369 | 0.252 | -31.8% |
| WooCommerce price filter | 0.235 | 0.233 | -0.6% |
| Bulk meta read (500 rows) | 0.681 | 0.637 | -6.5% |
| DATE() on indexed column | 0.611 | 0.605 | -1.1% |
That column of percentages is what noise looks like. Half of it goes the wrong way. The single big number, WooCommerce product listing at -31.8%, is 0.12ms in absolute terms.
So the reader was right. They didn’t notice a difference because there isn’t one to notice.
The one thing 10.6 does consistently worse is homepage throughput. It served roughly 7-13% fewer requests per second than 10.11, depending on concurrency, and it came last in both passes at every level. That’s the only 10.6 result I’d call real, and it’s still small.
10.11 to 11.4: this is the whole story
| Query | 10.11 | 11.4 | Change |
|---|---|---|---|
| UPDATE with subquery | 8.764 | 0.140 | -98.4% |
| DATE() on indexed column | 0.605 | 0.087 | -85.5% |
| Bulk meta read (500 rows) | 0.637 | 0.454 | -28.9% |
| Aggregate (posts per category) | 0.299 | 0.243 | -18.7% |
| Archive page (posts+meta+tax) | 3.809 | 3.308 | -13.2% |
| WooCommerce product listing | 0.252 | 0.282 | +12.1% |
| LIKE search | 0.103 | 0.107 | +3.4% |
Same result I got in March, on a rebuilt rig with different data and a different WordPress. That’s reassuring, because a benchmark that only reproduces on the machine that produced it isn’t worth much.
Two optimizer changes do almost all of it. Semi-join for UPDATE and DELETE, so a subquery in a DML statement gets planned properly instead of being re-run per row. And sargable date functions, so WHERE YEAR(post_date) = 2025 can use the index instead of scanning the table.
The 40x has a mirror image
This is the part I got wrong in March, or at least the part I didn’t dig into.
That “40x faster UPDATE” test uses a subquery that matches zero rows. It measures how the optimizer plans the statement, which is a real thing that real cleanup crons hit, but it isn’t the only shape those queries come in.
So I wrote a second test that runs the same statement shape against subqueries that do match rows, 15 times each, inside a transaction that gets rolled back so every run starts from the same state. Medians in ms:
| Test | Rows matched | 10.11 | 11.4 | 11.8 | 12.3 | 13.0-RC |
|---|---|---|---|---|---|---|
| A. UPDATE, subquery matches nothing | 0 | 9.062 | 0.130 | 0.135 | 0.143 | 0.135 |
| B. UPDATE postmeta by meta_key | 999 | 1.124 | 1.011 | 0.964 | 1.077 | 0.958 |
| C. DELETE postmeta by meta_key | 999 | 2.665 | 2.753 | 2.502 | 3.007 | 2.471 |
| D. UPDATE all meta of all products | 1,800 | 4.453 | 8.629 | 9.434 | 9.535 | 9.355 |
Test A is the headline, and it’s bigger than I reported in March: 70x, not 40x.
Tests B and C are flat. When there’s a usable index on the table you’re updating, every version picks the same plan and runs at the same speed.
Test D is 11.4 running twice as slow as 10.11. And it stays twice as slow through 11.8, 12.3 and 13.0. I ran it twice on separate rebuilds and got the same thing both times.
EXPLAIN says why. On 10.11:
PRIMARY wp_postmeta index key=PRIMARY rows=7761 Using where
DEPENDENT SUBQUERY wp_posts unique_subquery key=PRIMARY rows=1
On 11.4 and everything after:
PRIMARY wp_posts ref key=type_status_date rows=200 Using where; Using index
PRIMARY wp_postmeta ref key=post_id rows=6
10.11 walks 7,761 postmeta rows in order and checks each one. 11.4 flips the driving table, finds the 200 products first, then does 200 separate index lookups into postmeta. Fewer rows examined, more random access, and on this dataset the sequential scan wins.
Worth being honest about the limits here: 7,798 postmeta rows is small and the whole thing sits in the buffer pool. On a table big enough that the sequential scan hits disk, the new plan probably wins instead. I haven’t tested that, so I’m not going to claim it.
The practical version: 4ms against 9ms doesn’t matter unless something runs it in a loop. I’d still take 11.4. But it’s a good reminder to distrust anyone quoting a single benchmark number, me in March included.
Everything after 11.4 is flat
This one I’m showing as both passes, pass 1 / pass 2, because the averages flatter these versions than the data supports:
| Query | 11.4 | 11.8 | 12.3 | 13.0-RC |
|---|---|---|---|---|
| Autoloaded options | 0.081 / 0.077 | 0.075 / 0.076 | 0.078 / 0.043 | 0.079 / 0.075 |
| Single post + meta | 0.170 / 0.155 | 0.160 / 0.162 | 0.137 / 0.109 | 0.148 / 0.134 |
| Archive page (posts+meta+tax) | 3.603 / 3.014 | 2.941 / 2.921 | 3.098 / 3.558 | 2.923 / 2.861 |
| UPDATE with subquery | 0.140 / 0.139 | 0.143 / 0.149 | 0.130 / 0.133 | 0.137 / 0.134 |
| Bulk meta read (500 rows) | 0.454 / 0.453 | 0.439 / 0.443 | 0.430 / 0.452 | 0.408 / 0.364 |
| DATE() on indexed column | 0.093 / 0.082 | 0.088 / 0.084 | 0.087 / 0.088 | 0.083 / 0.028 |
| WooCommerce price filter | 0.242 / 0.229 | 0.226 / 0.218 | 0.216 / 0.228 | 0.225 / 0.160 |
Look at 12.3’s autoloaded options, 0.078 in one pass and 0.043 in the other. Or 13.0’s DATE() query, 0.083 then 0.028. Same container, same dump, an hour apart. On queries that finish in under a tenth of a millisecond, a single pass tells you almost nothing, and if I’d only run the matrix once I’d be writing “13.0 makes date queries 3x faster than 12.3” right now.
The archive page join is the one change I’d call real: about 11% faster on 11.8, and it holds in both passes and stays through 13.0. Everything else on that table is the machine breathing.
11.8 and 12.3 both got real work in the optimizer. Cost-based subquery strategies for UPDATE and DELETE in 11.8, index condition pushdown on reverse scans and loose index scan on descending keys in 12.3. None of it lands on the queries WordPress actually sends.
Page load and throughput: flat across all six
| Page TTFB (ms) | 10.6 | 10.11 | 11.4 | 11.8 | 12.3 | 13.0-RC |
|---|---|---|---|---|---|---|
| Homepage | 53.1 | 52.1 | 51.1 | 51.6 | 54.0 | 52.7 |
| Single post | 21.9 | 21.3 | 22.6 | 21.3 | 23.6 | 21.9 |
| Category archive | 22.3 | 22.5 | 22.8 | 22.6 | 23.4 | 23.4 |
| Shop page | 43.1 | 43.2 | 43.2 | 43.5 | 44.1 | 45.5 |
| REST posts | 57.2 | 54.3 | 54.5 | 56.5 | 57.2 | 56.4 |
Before anyone reads a winner out of that table: when I benchmarked the same version twice on the same machine an hour apart, homepage TTFB moved by up to 11.6%. That’s my noise floor. Every difference in that table is below it.
In March I reported 4-10% faster page loads for 11.4 and presented it as a real gain. With a noise measurement in hand I don’t think that was justified. The SQL numbers were solid, the TTFB numbers were within drift.
Which makes sense once you look at where the time goes. A 3.3ms query inside a 52ms response is 6% of the total. Cut it in half and you save 1.6ms. PHP is doing the rest of the work.
The “4x write performance” claim
MariaDB’s own 12.3 announcement leads with 4x write performance. I tested the WordPress write path directly through wp eval-file, so no HTTP round trip in the numbers. Milliseconds:
| Operation | 10.6 | 10.11 | 11.4 | 11.8 | 12.3 | 13.0-RC |
|---|---|---|---|---|---|---|
| wp_insert_post + 4 meta rows | 4.382 | 4.028 | 4.591 | 4.346 | 4.524 | 4.412 |
| update_post_meta | 0.288 | 0.282 | 0.287 | 0.278 | 0.315 | 0.262 |
| wp_update_post | 3.144 | 3.123 | 3.078 | 3.248 | 3.129 | 2.883 |
Nothing. Whatever workload that 4x describes, publishing a post isn’t it.
One correction while I’m here: the write test in my March post was broken. It created posts by POSTing to /wp-json/wp/v2/posts with curl --user admin:password. WordPress core rejects HTTP Basic auth, so that loop was timing rejected requests, not inserts. The “2.5% faster on writes” line in that post measured nothing. This version runs through WP-CLI instead.
What actually changed that can break you
Two defaults moved, and both are more likely to bite you than any of the performance numbers above.
innodb_snapshot_isolation is ON from 11.8 onwards. It was OFF in 10.6, 10.11 and 11.4. Under concurrent writes to the same row you can now get “Record has changed since last read” errors instead of silent last-write-wins. That’s correct behaviour and it’s why they changed it, but a WooCommerce store with a busy checkout is exactly where you’d meet it. Test on staging with real concurrency, not with one browser tab.
The default collation changed to utf8mb4_uca1400_ai_ci in 11.4. Your existing tables are fine, WordPress sets its own collation when it creates them. New tables created by plugins that don’t specify one will pick up the new default, and joining those against a utf8mb4_unicode_520_ci core table gives you “Illegal mix of collations”. I didn’t hit it in this test, but I’ve seen it in the wild.
Nothing else broke. WordPress 7.1, WooCommerce 11.0.1 and PHP 8.4 ran clean on all six versions including the 13.0 release candidate.
So what should you do
On 10.6: update. Not for speed, for support. Community support ended July 6, 2026, so you’re running an unpatched database. Going to 10.11 buys you until February 2028 and changes nothing else. Going to 11.4 or 11.8 buys you real query improvements and support into 2028-2029.
On 10.11: this is the upgrade that pays. 11.4 or 11.8, whichever your host offers. If they offer both, take 11.8, it’s supported to June 2028 and the archive query is a bit quicker.
On 11.4 or newer: stay. There’s nothing in 11.8, 12.3 or 13.0 that a WordPress site will feel. Upgrade when your support window gets close, not for performance.
Thinking about 13.0: don’t, it’s a release candidate. It performed fine, which is what I’d expect, but a release candidate under your client’s store is a bad trade for zero measurable gain.
And if the hosting panel offers 12.3 as the default, take it. It’s an LTS, supported to June 2029, and it’s not slower. Just don’t expect the upgrade itself to speed anything up.
The thing I’d actually do with an afternoon, if the goal is a faster site: object caching and a look at what your slowest plugin queries are doing. The database version stopped being the bottleneck at 11.4.
How I tested: one Docker stack at a time on an Apple Silicon Mac, 6 CPUs and 8GB allocated to the VM. WordPress 7.1, PHP 8.4.24, WooCommerce 11.0.1, stock MariaDB config. The dataset is built once on 10.6, dumped, and imported into each version, with ANALYZE TABLE run on every table after import so optimizer statistics are deterministic. SQL tests: 25 runs each, median. TTFB: 20 runs per page, median. Throughput: Apache Bench, 200 requests at concurrency 1, 5, 10 and 25. Writes: 200 inserts, 500 meta updates and 200 post updates through wp eval-file. Every number above is from two full passes, the second run in reverse version order. Where the two passes disagreed by more than a few percent I’ve said so.
Join developers and agency owners who get backend optimization strategies, tool releases, and deep-dive guides.
No spam. Unsubscribe anytime. I respect your privacy.
![MariaDB 10.6 to 13.0 for WordPress: Only One Upgrade Actually Does Anything [Benchmark] - MakeWPFast](https://makewpfast.com/og-image/64682.png)