Back to benchmark index

WooCommerce 5GB SQLite Benchmark: Visual Report

This is a merged PR assessment: it adds SQLite PR #378 to the existing MariaDB, SQLite rc3, and stable-control WooCommerce matrix at concurrent-request points 4, 16, 32, 64. The clearest view is not a box plot: each matrix cell has only three repetitions, so this report uses heatmaps, scatter plots, and repetition dot plots with median marks.

0SQLite rc3 failed flows / lock errors
361stable-control failed checkout flows
3,438stable-control SQLite lock/busy errors
0SQLite PR #378 failed flows / lock errors

Read the heatmap first. Green means SQLite rc3 improved that metric compared with MariaDB; red means it regressed. For latency metrics, green means lower latency. For throughput metrics, green means more completed work.

PR #378 vs rc3 Summary

This PR branch did not show a broad 2x-3x improvement on the measured WooCommerce 5GB request-load flows. It helped a few mid-concurrency cells, but regressed several high-concurrency p95 and throughput cells. Neither rc3 nor PR #378 logged SQLite lock/busy errors in this diagnostic.

WorkloadConcurrent requestsPR p95 vs rc3PR avg completion vs rc3PR throughput vs rc3
read-heavy4+8.8%+6.3%-6.0%
read-heavy16-4.3%-0.4%+0.5%
read-heavy32-0.8%+6.3%-6.3%
read-heavy64+39.4%+36.2%-27.1%
balanced16-11.8%-3.1%+3.0%
balanced64+29.8%+30.7%-24.1%
write-heavy32+9.1%+11.7%-10.1%
write-heavy64+16.1%+23.9%-20.6%

How The Test Was Conducted

The measured window starts after fixture restore, server startup, login setup, and warm-up. These are browser-equivalent WooCommerce flows driven over HTTP, not literal Chrome automation.

  1. Create one fresh WordPress site per database variant from the same WordPress package.
  2. Install the SQLite driver or configure MariaDB, install WooCommerce, and generate the same seeded 5GB WooCommerce fixture for every variant.
  3. Before every measured cell, restore that variant's clean database snapshot so earlier writes do not affect the next run.
  4. Start local nginx and PHP-FPM for that one case, then create logged-in worker sessions outside the measured timing window.
  5. Warm the site for 10 seconds, then measure for 30 seconds with the configured number of concurrent workers.
  6. The load generator did not open Chrome; it issued browser-equivalent HTTP requests for the same user journeys.
  7. Public browse flow: visit the shop/home page, open product pages, and perform catalog searches.
  8. Cart flow: open a product page, submit add-to-cart, and load the cart page.
  9. Checkout flow: add a product, open checkout, submit the WooCommerce order form with benchmark billing details, and verify that an order was created.
  10. Admin read flow: log in as an administrator and open WooCommerce order-admin screens.
  11. Repeat each workload/concurrent-request/variant cell three times and report medians, plus failures, write verification, WAL size, and SQLite lock/busy logs.

1. SQLite rc3 vs MariaDB: 3x4 Delta Heatmaps

SQLite rc3 versus MariaDB heatmaps
The p95 row can be green while average request time and throughput are red. That means SQLite had fewer completed flows and slower average requests, but a lower tail among the flows that completed.

2. Throughput vs Tail Latency

Throughput versus p95 latency scatter plot
Each point is one variant/workload/concurrent-request median. Numeric point labels are concurrent requests. Better points move right and down.

3. Repetition Spread Instead Of Boxplots

p95 repetition dot plots
Every dot is one repetition. The thick small bar is the median. This is more honest than a box-and-whisker plot for only three repetitions per cell.

4. Writes And Lock Contention

Write throughput and stable-control lock errors
MariaDB keeps the highest verified write rate. SQLite rc3 completes cleanly but with lower write throughput. The stable control shows real lock-related checkout failures.

5. What The SQLite Lock/Busy Errors Mean

Important distinction: HTTP status errors and benchmark flow failures are different. A request can return HTTP 200 and still fail the benchmark if the expected user outcome did not happen.

The high-lock cell is SQLite stable control, write-heavy, 64 concurrent requests: 771 SQLite lock/busy log events while serving 2,371 measured HTTP requests across 883 benchmark flows. Every measured HTTP request returned status 200; there were 0 HTTP 500 responses.

The consequence was still user-visible: 111 checkout flows failed semantic verification. The failing checkout paths returned ordinary WooCommerce pages with status 200, but the checkout nonce/session state was missing and no order was verified. The benchmark did not retry those failed flows at the application level.

The read-heavy stable-control cases also logged lock errors because they were not database-write-free. They had 234 lock/busy events across 12,018 measured HTTP requests and 0 failed flows. Product and admin read pages triggered writes for Action Scheduler claims and WooCommerce/WordPress transients such as shipping-method counts, related-product caches, and customer/report caches. Those writes were non-critical for the rendered page, so the responses stayed 200.

ScopeHTTP requestsStatus mixHTTP 5xxHTTP non-2xxBenchmark failed flowsWrite verification failuresSQLite lock/busy events
MariaDB baseline48,738200: 48,7380 (0.00%)0 (0.00%)0 (0.00%)00
SQLite rc338,792200: 38,7920 (0.00%)0 (0.00%)0 (0.00%)00
SQLite stable control33,471200: 33,4710 (0.00%)0 (0.00%)361 (1.67%)3613,438
All SQLite variants combined108,279200: 108,2790 (0.00%)0 (0.00%)361 (0.53%)3613,438
Stable 64 concurrent requests detailFlowsHTTP requestsStatus mixHTTP 5xxBenchmark failed flowsWrite verification failuresSQLite lock/busy events
stable write-heavy, 64 concurrent requests, all reps8832,371200: 2,3710 (0.00%)111 (12.57%)111771
rep13841,047200: 1,0470 (0.00%)34 (8.85%)34292
rep2276735200: 7350 (0.00%)41 (14.86%)41274
rep3223589200: 5890 (0.00%)36 (16.14%)36205

Variant Totals

VariantMedian flows/sec across cellsFailed flowsWrite verification failuresSQLite lock/busy errors
MariaDB23.82000
SQLite rc317.84000
SQLite stable15.563613613,438
SQLite PR #37817.07000

SQLite rc3 Delta Table

WorkloadConcurrent requestsThroughputAvg request timep95 latencyVerified writes/sec
read-heavy412.8% lower14.7% slower18.6% slowern/a
read-heavy1620.3% lower25.2% slower5.5% fastern/a
read-heavy3218.4% lower22.5% slower20.6% fastern/a
read-heavy6427.1% lower36.6% slower20.7% fastern/a
balanced46.2% higher3.3% faster1.7% faster2.3% lower
balanced1623.7% lower31.8% slower1.0% slower30.0% lower
balanced3224.5% lower34.7% slower13.5% faster27.8% lower
balanced6432.6% lower49.1% slower13.6% faster32.3% lower
write-heavy413.0% higher12.3% faster7.6% faster9.0% higher
write-heavy1615.5% lower17.7% slower10.4% slower16.0% lower
write-heavy3224.7% lower33.8% slower33.9% slower26.9% lower
write-heavy6432.3% lower48.5% slower40.0% slower32.5% lower

Method Note

This visual report is generated from aggregate.csv, results.csv, and results.json. It does not rerun the benchmark. The benchmark restored a database snapshot before every measured case, excluded setup/login from the measured window, used a 10s warm-up, measured 30s, and repeated every workload/concurrent-request cell three times.