Data source: post_type=rtc-perf-result on https://make.wordpress.org/hosting/, eight captures from 2026-04-29 through 2026-05-05.
Test runner: WordPress/distributed-rtc-performance-testing.
Strategies under test (all on WP 7.1-alpha):
| # | Approach | Key | PR |
|---|---|---|---|
| 1 | Post meta — RC2 baseline | post-meta |
— |
| 2 | Custom table for all data | custom-table |
#11256 |
| 3 | Post meta + transients for awareness | post-meta-transients |
#11348 |
| 4 | Custom table + object cache for awareness | custom-table-with-transients |
#11599 |
Captures are anonymised; provider relationships are noted where they're relevant for cross-cuts.
| Label | Hosting class | Persistent cache | PHP | WP rev | Notes |
|---|---|---|---|---|---|
| A | Shared | redis | 8.3 | 62278 | |
| B | Shared | redis | 8.3 | 62295 | Same provider as A (later WP rev) |
| C | Shared | none | 8.5 | 62295 | Same provider as A, B (different PHP, no cache) |
| D | Shared | none | 8.1 | 62290 | |
| E | Shared | none | 8.2 | 62278 | Same provider as D (earlier capture) |
| F |
Shared | none | 8.2 | 62290 | Anomalous transient pathology |
| G | Managed cloud | memcached | 8.4 | 62278 | |
| H | Shared | none | 8.1 | 62295 | Slow bootstrap, otherwise normal |
A ninth, partial capture (PHP 8.0, no cache) ran only the post-meta strategy and is excluded from cross-strategy tables below.
"No persistent cache" = no object-cache.php drop-in; WordPress falls back to its built-in WP_Object_Cache class which is per-request, in-memory only.
The runner logs every test request via rest_pre_dispatch / rest_post_dispatch hooks (rtc-test.php:178–290):
- dispatch ms (
mean_disp_ms) — wall time spent inside the REST handler. This is the part the strategies actually affect. - total ms (
mean_total_ms) — full request fromREQUEST_TIME_FLOATto end of dispatch. Includes WP bootstrap; mostly host-architecture, not strategy. - DB queries / DB time — measured during dispatch only.
- n — number of polled requests aggregated.
sustainruns for a fixed 30s window with N concurrent clients, so n=68–300+.
All numbers below are weighted by sample size across the 6 variants (poll_delay × update_size).
| Environment | post-meta | custom-table | post-meta-trans | ct-with-trans |
|---|---|---|---|---|
| B — Shared / redis / PHP 8.3 (62295) | 2.17 | 1.14 | 1.08 | 0.87 |
| A — Shared / redis / PHP 8.3 (62278) | 2.07 | 2.05 | 1.39 | 0.95 |
| D — Shared / no cache / PHP 8.1 | 2.28 | 0.90 | 2.17 | 0.98 |
| E — Shared / no cache / PHP 8.2 | 2.79 | 1.28 | 2.74 | 1.33 |
| C — Shared / no cache / PHP 8.5 | 2.63 | 1.50 | 1.93 | 1.14 |
| G — Managed cloud / memcached | 4.70 | 3.94 | 2.99 | 2.47 |
| H — Shared / no cache / PHP 8.1 | 14.35 | 9.16 | 12.76 | 9.33 |
| F — Shared / no cache / PHP 8.2 |
5.54 | 6.22 | 26.07 | 12.10 |
Bold = winner per row. post-meta (the RC2 baseline) is last on every environment.
| Environment | custom-table | post-meta-trans | ct-with-trans |
|---|---|---|---|
| B — Shared / redis | −47% | −50% | −60% |
| D — Shared / no cache (PHP 8.1) | −60% | −5% | −57% |
| E — Shared / no cache (PHP 8.2) | −54% | −2% | −52% |
| C — Shared / no cache (PHP 8.5) | −43% | −27% | −57% |
| A — Shared / redis | −1% | −33% | −54% |
| G — Managed cloud / memcached | −16% | −36% | −47% |
| H — Shared / no cache (PHP 8.1) | −36% | −11% | −35% |
| F — Shared / no cache |
+12% | +371% | +118% |
custom-table-with-transients is first or tied-first on six of seven complete environments and never worse than post-meta. Two patterns to note:
- No-cache shared environments (D, E, H):
custom-table(no transients) is a hair faster thancustom-table-with-transients— within 0.05–0.17 ms. The transient layer adds no value when there's no persistent cache to serve it from, so the win comes purely from the schema. - Environment F: see anomaly section.
| Environment | post-meta | custom-table | post-meta-trans | ct-with-trans |
|---|---|---|---|---|
| B — Shared / redis | 6.00 | 2.16 | 1.00 | 1.00 |
| A — Shared / redis | 6.00 | 4.00 | 1.00 | 1.00 |
| G — Managed cloud / memcached | 6.00 | 4.00 | 1.00 | 1.00 |
| C — Shared / no cache (PHP 8.5) | 8.00 | 4.15 | 6.11 | 4.10 |
| D — Shared / no cache (PHP 8.1) | 9.00 | 5.15 | 8.07 | 5.03 |
| E — Shared / no cache (PHP 8.2) | 9.00 | 5.20 | 8.14 | 5.14 |
| H — Shared / no cache (PHP 8.1) | 9.00 | 5.25 | 8.20 | 5.16 |
| F — Shared / no cache |
9.00 | 5.37 | 8.21 | 5.22 |
Two very clean signals:
- Persistent cache → 1 query for both transient strategies. Without it, transients fall through to the options table and behave roughly like the post-meta path.
- Custom table → ~half the queries of post meta on every environment, regardless of cache.
custom-table-with-transients wins because it gets the schema reduction when caching is absent, and the cache reduction when it's present.
Environments B and C are from the same provider; PHP versions differ (8.3 vs 8.5), but the cache config is the only deliberate change:
| Strategy | B (redis) | C (no cache) | Penalty for losing cache |
|---|---|---|---|
| post-meta | 2.17 ms | 2.63 ms | +21% |
| custom-table | 1.14 ms | 1.50 ms | +31% |
| post-meta-transients | 1.08 ms | 1.93 ms | +79% |
| custom-table-with-transients | 0.87 ms | 1.14 ms | +31% |
The strategies that lean hardest on the cache pay the most when it's gone. post-meta-transients nearly doubles in latency without persistent cache — useful if anyone considers it a fallback default.
Environments A and B are the same provider, same hosting tier, same PHP, both on redis — only the WP rev changes. The latency change isn't environmental:
| Strategy | A (62278) | B (62295) | Δ | DB queries Δ |
|---|---|---|---|---|
| post-meta | 2.07 ms | 2.17 ms | +5% | unchanged |
| custom-table | 2.05 ms | 1.14 ms | −44% | 4.00 → 2.16 |
| post-meta-transients | 1.39 ms | 1.08 ms | −23% | unchanged (1.00) |
| custom-table-with-transients | 0.95 ms | 0.87 ms | −8% | unchanged (1.00) |
custom-table got materially faster between revs — about half its DB queries went away. Worth identifying which commit and confirming it doesn't regress the cached path. (It looks neutral-to-positive there, but the signal is smaller than test noise.)
| Environment | total ms | total CPU ms |
|---|---|---|
| F — Shared / no cache | 44 | 17 |
| D — Shared / no cache (PHP 8.1) | 46 | 31 |
| C — Shared / no cache (PHP 8.5) | 50 | 37 |
| B — Shared / redis | 55 | 41 |
| A — Shared / redis | 56 | 42 |
| H — Shared / no cache (PHP 8.1) | 199 | 60 |
| E — Shared / no cache (PHP 8.2) |
212 | 53 |
| G — Managed cloud / memcached | 630 | 427 |
The managed cloud platform's per-request cost is consistent across two weeks (~630 ms total, ~430 ms total CPU) — it's an architectural property of that platform, not a one-off. Most RTC dispatch optimisations are <1% of that budget, so the request-handling overhead in that platform likely deserves its own investigation independent of RTC storage strategy.
Environment H's bootstrap is ~4× slower than other no-cache shared environments (199 ms vs 44–50 ms), with elevated CPU as well. That's why H's dispatch numbers are roughly ~5× larger than D, E, or C on the same custom-table strategy: the strategy is doing the same work, the host is just slower on every code path. The strategy ranking is preserved, just compressed (−36% best vs −60% on D).
Environment E sits ~5× above its sister capture D (same provider, different PHP / different day). That looks like environmental noise on E's capture day — treat that row's total_ms figures with caution. Dispatch-only numbers are unaffected.
| Strategy | F dispatch | Other no-cache environments |
|---|---|---|
| post-meta | 5.54 ms | 2.3–14.4 ms |
| custom-table | 6.22 ms | 0.9–9.2 ms |
| post-meta-transients | 26.07 ms | 1.9–12.8 ms |
| custom-table-with-transients | 12.10 ms | 1.0–9.3 ms |
The non-transient paths are merely slow. The transient paths are pathological — even compared to environment H (the next-slowest no-cache host), F's post-meta-transients is 2× slower. Likely candidates worth investigating with the hosting provider:
- Slow
optionstable writes (autoload list churn from transient set/expire cycles?) - Missing or unused index on
wp_options.option_name - Per-request schema introspection (
SHOW COLUMNS) hitting a cold path
F's bootstrap is actually the leanest in the cohort (17 ms total CPU), so this isn't a generally-slow host — it's specifically the transient code path that misbehaves there. Recommend reaching out to that provider before drawing conclusions for similarly-tiered hosting in general.
Ship custom-table-with-transients (#11599) as the default RTC storage strategy.
- First or tied-first on six of seven complete environments (excludes the F anomaly; ties closely with
custom-tableon no-cache shared environments D, E, H). - Best worst case among the candidates — never slower than the RC2 baseline, and on F it's safer than
post-meta-transients. - Degrades gracefully without persistent cache: within 0.05–0.17 ms of plain
custom-tableon every no-cache shared host, comfortably ahead of the post-meta variants. - Best cache utilisation when caching is present: drops to 1 DB query per dispatch on both redis and memcached, beating both
post-meta-transients(which has the same cache profile but worse schema) andcustom-table(which has the same schema but doesn't benefit from cache).
Avoid post-meta-transients as a fallback default: on no-cache environments it is at best a small win (H −11%, C −27%), at worst within noise of raw post-meta (D/E −2 to −5%), and on environment F it's catastrophic.
- Sample size:
sustainis the load to trust (n=68–300+ per variant).single-idle(n=10) is too noisy for ranking. - Per-environment, single capture: each environment is one test run. Day-to-day noise (the environment E
total_msoutlier) can move dispatch numbers by 10–30%; the strategy ranking has been stable across captures, but absolute deltas should be read as a band, not a point. - Cache-effect comparison (B vs C) is confounded by PHP version (8.3 vs 8.5). The directional signal is consistent with the rest of the data but a clean controlled comparison would need the same PHP across both cache configurations.
- Each
rtc-perf-resultpost is one host's submission, not aggregated; running the test multiple times produces additional posts. - One partial capture (PHP 8.0, no cache) ran only
post-metaand is excluded from cross-strategy comparison.
- Identify the WP core commit between revs 62278 and 62295 that halved
custom-table's DB queries. Confirm intentional and forward-port tocustom-table-with-transientsif there's anything more to be gained. - Environment F transient pathology: needs a host-side trace. Reproduce with
WP_DEBUG_LOG+SAVEQUERIESand look at the slow query log for the 30s window. - Managed cloud bootstrap (G): 630 ms is real and consistent. Out of scope for RTC, but it is the dominant variable in that platform's user-perceived latency for any small REST endpoint.
- Environment H bootstrap: 199 ms is ~4× slower than other no-cache shared environments. Not pathological, but worth confirming with the provider whether this represents typical traffic or a cold-cache run.
- More captures: only one persistent-cache config per cache-type so far. A second capture per environment would help disentangle environmental noise from strategy effects in the Δ-vs-baseline column.
Source code: WordPress/distributed-rtc-performance-testing. Underlying captures live on https://make.wordpress.org/hosting/ as rtc-perf-result posts; identifiers withheld here per the call-for-testing commitment.