
# Benchmarks

A cache raises two questions: **how much does it help, and what does it cost?** No single number answers both, so this page reports several. Everything below comes from one run of the benchmark harness in [`bench/`](https://github.com/unjs/ocache/tree/main/bench): Node v24.19.0, seed 1, load profile `steady`, 7 scenarios, 26 cached configurations, 31,718 measured requests.

None of the numbers on this page are typed by hand. They are all filled in from the run's JSON when the page is generated, so you can re-run the benchmark on your own hardware and regenerate the page to see your own results.

The whole run in one figure: every workload with ocache against the same workload without it, ranked by how much p99 latency improved, over the medians across all of them. Each row here shows one storage backend — the chart names it — and one offered rate; the rest of this page takes that apart.

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 350" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>ocache under load</title><desc>p99 latency with and without ocache for 7 workloads, origin-call reduction against each no-cache baseline, and the medians across all of them.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="350" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">ocache under load</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">7 workloads, each run twice at the same offered rate: once through ocache on memory storage, once with no cache in the</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">path. Both runs use the same seed, so the only difference between the two marks on a row is the cache.</text><text x="16" y="96" font-size="21" fill="#0b0b0b" class="f-ink" font-weight="600">2.8x</text><text x="16" y="111" font-size="10" fill="#898781" class="f-muted">median p99 latency improvement</text><text x="208" y="96" font-size="21" fill="#0b0b0b" class="f-ink" font-weight="600">93%</text><text x="208" y="111" font-size="10" fill="#898781" class="f-muted">median origin-call reduction</text><text x="400" y="96" font-size="21" fill="#0b0b0b" class="f-ink" font-weight="600">-56%</text><text x="400" y="111" font-size="10" fill="#898781" class="f-muted">median CPU per request</text><text x="592" y="96" font-size="21" fill="#0b0b0b" class="f-ink" font-weight="600">+22 µs</text><text x="592" y="111" font-size="10" fill="#898781" class="f-muted">median cost of one cache hit</text><circle cx="20" cy="124" r="4" fill="#a9a7a0" class="f-deemph"/><text x="30" y="128" font-size="11" fill="#52514e" class="f-ink2">no cache</text><circle cx="103.04" cy="124" r="4" fill="#2a78d6" class="f-s1"/><text x="113.04" y="128" font-size="11" fill="#52514e" class="f-ink2">with ocache</text><text x="664" y="128" font-size="10" fill="#898781" class="f-muted" text-anchor="end">faster</text><text x="788" y="128" font-size="10" fill="#898781" class="f-muted" text-anchor="end">origin-call reduction</text><line x1="227.40" y1="134" x2="227.40" y2="306" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="227.40" y="321" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="293.12" y1="134" x2="293.12" y2="306" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="293.12" y="321" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="358.84" y1="134" x2="358.84" y2="306" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="358.84" y="321" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="424.56" y1="134" x2="424.56" y2="306" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="424.56" y="321" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="490.28" y1="134" x2="490.28" y2="306" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="490.28" y="321" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1,000</text><line x1="556" y1="134" x2="556" y2="306" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="556" y="321" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10,000</text><line x1="227.40" y1="306" x2="556" y2="306" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="215.40" y="154" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">Rate-limited upstream proxy</text><line x1="261.82" y1="150" x2="486.14" y2="150" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="486.14" cy="150" r="4" fill="#a9a7a0" stroke="#fcfcfb" class="f-deemph k-surface" stroke-width="2"/><circle cx="261.82" cy="150" r="4" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><text x="253.82" y="153.50" font-size="10" fill="#52514e" class="f-ink2" text-anchor="end">0.33</text><text x="494.14" y="153.50" font-size="10" fill="#52514e" class="f-ink2">865</text><text x="664" y="154" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">2,590x</text><path d="M676,145 H738 A4,4 0 0 1 742,149 V151 A4,4 0 0 1 738,155 H676 Z" fill="#e1e0d9" class="f-grid"/><path d="M676,145 H733.64 A4,4 0 0 1 737.64,149 V151 A4,4 0 0 1 733.64,155 H676 Z" fill="#eb6834" class="f-s2"/><text x="788" y="154" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">93%</text><text x="215.40" y="178" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">Markdown render (function)</text><line x1="385.17" y1="174" x2="475.51" y2="174" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="475.51" cy="174" r="4" fill="#a9a7a0" stroke="#fcfcfb" class="f-deemph k-surface" stroke-width="2"/><circle cx="385.17" cy="174" r="4" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><text x="377.17" y="177.50" font-size="10" fill="#52514e" class="f-ink2" text-anchor="end">25.16</text><text x="483.51" y="177.50" font-size="10" fill="#52514e" class="f-ink2">596</text><text x="664" y="178" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">23.7x</text><path d="M676,169 H738 A4,4 0 0 1 742,173 V175 A4,4 0 0 1 738,179 H676 Z" fill="#e1e0d9" class="f-grid"/><path d="M676,169 H733.18 A4,4 0 0 1 737.18,173 V175 A4,4 0 0 1 733.18,179 H676 Z" fill="#eb6834" class="f-s2"/><text x="788" y="178" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">93%</text><text x="215.40" y="202" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">OG image render</text><line x1="441.96" y1="198" x2="496.17" y2="198" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="496.17" cy="198" r="4" fill="#a9a7a0" stroke="#fcfcfb" class="f-deemph k-surface" stroke-width="2"/><circle cx="441.96" cy="198" r="4" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><text x="433.96" y="201.50" font-size="10" fill="#52514e" class="f-ink2" text-anchor="end">184</text><text x="504.17" y="201.50" font-size="10" fill="#52514e" class="f-ink2">1229</text><text x="664" y="202" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">6.7x</text><path d="M676,193 H738 A4,4 0 0 1 742,197 V199 A4,4 0 0 1 738,203 H676 Z" fill="#e1e0d9" class="f-grid"/><path d="M676,193 H736.71 A4,4 0 0 1 740.71,197 V199 A4,4 0 0 1 736.71,203 H676 Z" fill="#eb6834" class="f-s2"/><text x="788" y="202" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">98%</text><text x="215.40" y="226" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">SSR product page</text><line x1="399.98" y1="222" x2="429.79" y2="222" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="429.79" cy="222" r="4" fill="#a9a7a0" stroke="#fcfcfb" class="f-deemph k-surface" stroke-width="2"/><circle cx="399.98" cy="222" r="4" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><text x="391.98" y="225.50" font-size="10" fill="#52514e" class="f-ink2" text-anchor="end">42.27</text><text x="437.79" y="225.50" font-size="10" fill="#52514e" class="f-ink2">120</text><text x="664" y="226" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">2.8x</text><path d="M676,217 H738 A4,4 0 0 1 742,221 V223 A4,4 0 0 1 738,227 H676 Z" fill="#e1e0d9" class="f-grid"/><path d="M676,217 H733.71 A4,4 0 0 1 737.71,221 V223 A4,4 0 0 1 733.71,227 H676 Z" fill="#eb6834" class="f-s2"/><text x="788" y="226" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">94%</text><text x="215.40" y="250" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">JSON list API</text><line x1="400.25" y1="246" x2="419.72" y2="246" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="419.72" cy="246" r="4" fill="#a9a7a0" stroke="#fcfcfb" class="f-deemph k-surface" stroke-width="2"/><circle cx="400.25" cy="246" r="4" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><text x="392.25" y="249.50" font-size="10" fill="#52514e" class="f-ink2" text-anchor="end">42.66</text><text x="427.72" y="249.50" font-size="10" fill="#52514e" class="f-ink2">84.42</text><text x="664" y="250" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">2.0x</text><path d="M676,241 H738 A4,4 0 0 1 742,245 V247 A4,4 0 0 1 738,251 H676 Z" fill="#e1e0d9" class="f-grid"/><path d="M676,241 H733.39 A4,4 0 0 1 737.39,245 V247 A4,4 0 0 1 733.39,251 H676 Z" fill="#eb6834" class="f-s2"/><text x="788" y="250" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">93%</text><text x="215.40" y="274" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">Fan-out aggregation (function)</text><line x1="467.50" y1="270" x2="483.40" y2="270" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="483.40" cy="270" r="4" fill="#a9a7a0" stroke="#fcfcfb" class="f-deemph k-surface" stroke-width="2"/><circle cx="467.50" cy="270" r="4" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><text x="459.50" y="273.50" font-size="10" fill="#52514e" class="f-ink2" text-anchor="end">450</text><text x="491.40" y="273.50" font-size="10" fill="#52514e" class="f-ink2">786</text><text x="664" y="274" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">1.7x</text><path d="M676,265 H738 A4,4 0 0 1 742,269 V271 A4,4 0 0 1 738,275 H676 Z" fill="#e1e0d9" class="f-grid"/><path d="M676,265 H723.02 A4,4 0 0 1 727.02,269 V271 A4,4 0 0 1 723.02,275 H676 Z" fill="#eb6834" class="f-s2"/><text x="788" y="274" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">77%</text><text x="215.40" y="298" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">Personalized dashboard</text><line x1="424.35" y1="294" x2="436.19" y2="294" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="436.19" cy="294" r="4" fill="#a9a7a0" stroke="#fcfcfb" class="f-deemph k-surface" stroke-width="2"/><circle cx="424.35" cy="294" r="4" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><text x="416.35" y="297.50" font-size="10" fill="#52514e" class="f-ink2" text-anchor="end">99.25</text><text x="444.19" y="297.50" font-size="10" fill="#52514e" class="f-ink2">150</text><text x="664" y="298" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">1.5x</text><path d="M676,289 H738 A4,4 0 0 1 742,293 V295 A4,4 0 0 1 738,299 H676 Z" fill="#e1e0d9" class="f-grid"/><path d="M676,289 H725.95 A4,4 0 0 1 729.95,293 V295 A4,4 0 0 1 725.95,299 H676 Z" fill="#eb6834" class="f-s2"/><text x="788" y="298" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">82%</text><text x="227.40" y="337" font-size="10" fill="#898781" class="f-muted">p99 latency in ms · log scale</text><text x="788" y="337" font-size="10" fill="#898781" class="f-muted" text-anchor="end">Node v24.19.0 · seed 1 · steady load</text></svg>
</div>

## How the benchmark works

Each scenario models a realistic workload rather than a library feature: a page render, a JSON list, a per-user dashboard, an image render, an upstream API with a rate cap. Every scenario runs **twice — once with ocache in the path and once without** — so the difference between the two rows is exactly what caching changed. The cached side is then repeated across several storage backends. Backend latency is simulated from real-world p50/p99 figures rather than set to zero. This run covers `memory`, `redis-local`, `redis-az`, `redis-az-bytes`, `sql`, `kv-edge`, `object-store`; each scenario uses the backends that make sense for it, and its chart lists which ones.

A backend name ending in `-bytes` is not a different backend. It is the same simulated wire
as its twin — `redis-az-bytes` and `redis-az` share one latency model exactly — running
through [`createBlobStorage`](/docs/storage#keeping-bodies-as-bytes-on-a-byte-only-driver), which
stores each entry as one byte frame instead of a JSON document. The pair is there so the
codec can be read off the difference between two rows rather than argued about.

A few choices keep the results honest:

- **Requests do not wait for each other.** They arrive on a fixed random schedule (a Poisson process), and latency is measured from when a request _should_ have started, not when the server got around to it. A benchmark that waits for each response before sending the next one hides queueing delay — the thing users actually feel under load.
- **Waiting and computing are modelled separately.** When the origin waits on I/O (a database, an upstream call), caching that away buys **latency**. When the origin computes on the main thread, caching it away buys **capacity** — the server can handle more traffic. Most scenarios include both.
- **Caches are warmed up first.** The hit ratio you see reflects the shape of the traffic, not how short the measurement was — which is what a long-running server actually experiences.
- **Both sides see identical traffic.** Same keys, same arrival times, same simulated latencies. The only difference is whether ocache is in the path.

> [!NOTE]
> Handlers are called directly in process — no network socket, no HTTP parser, no framework — so the absolute request rates are higher than a real deployment reaches. What matters is the comparison between the no-cache and cached rows, not the absolute numbers. The [harness README](https://github.com/unjs/ocache/blob/main/bench/README.md) explains the full method and its known limits.

## How much caching helps

| scenario                 | offered rps | no-cache p99 (ms) | cached p99 (ms) | p99 vs no cache | origin-call reduction |
| ------------------------ | ----------: | ----------------: | --------------: | --------------: | --------------------: |
| `ssr-product-page`       |          60 |               120 |     42.27–59.58 |     2.02x–2.84x |                 93.5% |
| `api-list`               |         300 |             84.42 |     42.66–57.44 |     1.47x–1.98x |                 93.0% |
| `personalized-dashboard` |         220 |               150 |       99.25–100 |     1.50x–1.51x |                 81.7% |
| `og-image`               |           4 |              1229 |         184–185 |     6.65x–6.68x |                 98.0% |
| `upstream-proxy`         |          25 |               865 |        0.33–102 |  8.46x–2589.70x |           92.7%–93.4% |
| `markdown-render`        |          30 |               596 |       25.16–113 |    5.26x–23.69x |                 92.7% |
| `fanout-aggregate`       |          90 |               786 |         450–461 |     1.70x–1.75x |           76.7%–77.3% |

Look at the whole range, not just the best row. Across every cached configuration in this run, p99 latency improves between 1.47x and 2589.70x, with a median of 2.81x. What sets the extremes is the origin, not the cache: when the origin is the bottleneck — a render that blocks the main thread, or an upstream that only allows so many requests at once — a cache hit removes an entire queue, not just one round trip, and the improvement becomes enormous. That is what happens to `upstream-proxy` at 2589.70x.

The scenario that gains the least is `personalized-dashboard`, at 1.51x even on its fastest backend — and yet it still reduces origin invocations by 81.7%. That is the point: **faster responses and less origin work are two separate wins**, and a workload can get one without the other. Hard cases like this one — per-user keys, short-lived sessions, many distinct keys — are included on purpose. A benchmark made only of easy wins would not tell you anything.

**Origin-call reduction** compares foreground and background origin invocations per admitted measured request with the matching no-cache row. It maps to origin work, but is deliberately not described as a request-level cache-hit share: deduplicated misses can share one invocation, while a stale response can launch a background refresh. Here it ranges from 76.7% to 98.0%, driven by traffic distribution and key cardinality:

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 828" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>Origin-call reduction</title><desc>Reduction in origin invocations per admitted measured request for each scenario and storage backend.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="828" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">Origin-call reduction</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">Reduction in origin invocations per admitted request against the matching no-cache row, including deduplication and</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">background refreshes. This — not the speedup — maps to origin work. The no-cache rows are left out.</text><line x1="153.22" y1="86" x2="153.22" y2="784" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><line x1="279.91" y1="86" x2="279.91" y2="784" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><line x1="406.61" y1="86" x2="406.61" y2="784" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><line x1="533.31" y1="86" x2="533.31" y2="784" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><line x1="660" y1="86" x2="660" y2="784" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="153.22" y="82" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0%</text><text x="279.91" y="82" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">25%</text><text x="406.61" y="82" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">50%</text><text x="533.31" y="82" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">75%</text><text x="660" y="82" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100%</text><text x="16" y="101" font-size="11" fill="#0b0b0b" class="f-ink" font-weight="600">ssr-product-page</text><text x="141.22" y="119" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><path d="M153.22,108 H623.08 A4,4 0 0 1 627.08,112 V118 A4,4 0 0 1 623.08,122 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="635.08" y="119" font-size="11" fill="#52514e" class="f-ink2">93.5%</text><text x="141.22" y="139" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><path d="M153.22,128 H623.08 A4,4 0 0 1 627.08,132 V138 A4,4 0 0 1 623.08,142 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="635.08" y="139" font-size="11" fill="#52514e" class="f-ink2">93.5%</text><text x="141.22" y="159" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az-bytes</text><path d="M153.22,148 H623.08 A4,4 0 0 1 627.08,152 V158 A4,4 0 0 1 623.08,162 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="635.08" y="159" font-size="11" fill="#52514e" class="f-ink2">93.5%</text><text x="141.22" y="179" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">kv-edge</text><path d="M153.22,168 H623.08 A4,4 0 0 1 627.08,172 V178 A4,4 0 0 1 623.08,182 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="635.08" y="179" font-size="11" fill="#52514e" class="f-ink2">93.5%</text><text x="16" y="207" font-size="11" fill="#0b0b0b" class="f-ink" font-weight="600">api-list</text><text x="141.22" y="225" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><path d="M153.22,214 H620.64 A4,4 0 0 1 624.64,218 V224 A4,4 0 0 1 620.64,228 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="632.64" y="225" font-size="11" fill="#52514e" class="f-ink2">93.0%</text><text x="141.22" y="245" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><path d="M153.22,234 H620.64 A4,4 0 0 1 624.64,238 V244 A4,4 0 0 1 620.64,248 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="632.64" y="245" font-size="11" fill="#52514e" class="f-ink2">93.0%</text><text x="141.22" y="265" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">kv-edge</text><path d="M153.22,254 H620.64 A4,4 0 0 1 624.64,258 V264 A4,4 0 0 1 620.64,268 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="632.64" y="265" font-size="11" fill="#52514e" class="f-ink2">93.0%</text><text x="16" y="293" font-size="11" fill="#0b0b0b" class="f-ink" font-weight="600">personalized-dashboard</text><text x="141.22" y="311" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><path d="M153.22,300 H563.45 A4,4 0 0 1 567.45,304 V310 A4,4 0 0 1 563.45,314 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="575.45" y="311" font-size="11" fill="#52514e" class="f-ink2">81.7%</text><text x="141.22" y="331" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><path d="M153.22,320 H563.45 A4,4 0 0 1 567.45,324 V330 A4,4 0 0 1 563.45,334 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="575.45" y="331" font-size="11" fill="#52514e" class="f-ink2">81.7%</text><text x="16" y="359" font-size="11" fill="#0b0b0b" class="f-ink" font-weight="600">og-image</text><text x="141.22" y="377" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><path d="M153.22,366 H646.06 A4,4 0 0 1 650.06,370 V376 A4,4 0 0 1 646.06,380 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="658.06" y="377" font-size="11" fill="#52514e" class="f-ink2">98.0%</text><text x="141.22" y="397" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><path d="M153.22,386 H646.06 A4,4 0 0 1 650.06,390 V396 A4,4 0 0 1 646.06,400 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="658.06" y="397" font-size="11" fill="#52514e" class="f-ink2">98.0%</text><text x="141.22" y="417" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az-bytes</text><path d="M153.22,406 H646.06 A4,4 0 0 1 650.06,410 V416 A4,4 0 0 1 646.06,420 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="658.06" y="417" font-size="11" fill="#52514e" class="f-ink2">98.0%</text><text x="16" y="445" font-size="11" fill="#0b0b0b" class="f-ink" font-weight="600">upstream-proxy</text><text x="141.22" y="463" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><path d="M153.22,452 H622.55 A4,4 0 0 1 626.55,456 V462 A4,4 0 0 1 622.55,466 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="634.55" y="463" font-size="11" fill="#52514e" class="f-ink2">93.4%</text><text x="141.22" y="483" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><path d="M153.22,472 H622.55 A4,4 0 0 1 626.55,476 V482 A4,4 0 0 1 622.55,486 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="634.55" y="483" font-size="11" fill="#52514e" class="f-ink2">93.4%</text><text x="141.22" y="503" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">object-store</text><path d="M153.22,492 H619.20 A4,4 0 0 1 623.20,496 V502 A4,4 0 0 1 619.20,506 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="631.20" y="503" font-size="11" fill="#52514e" class="f-ink2">92.7%</text><text x="16" y="531" font-size="11" fill="#0b0b0b" class="f-ink" font-weight="600">markdown-render</text><text x="141.22" y="549" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><path d="M153.22,538 H618.99 A4,4 0 0 1 622.99,542 V548 A4,4 0 0 1 618.99,552 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="630.99" y="549" font-size="11" fill="#52514e" class="f-ink2">92.7%</text><text x="141.22" y="569" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-local</text><path d="M153.22,558 H618.99 A4,4 0 0 1 622.99,562 V568 A4,4 0 0 1 618.99,572 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="630.99" y="569" font-size="11" fill="#52514e" class="f-ink2">92.7%</text><text x="141.22" y="589" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><path d="M153.22,578 H618.99 A4,4 0 0 1 622.99,582 V588 A4,4 0 0 1 618.99,592 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="630.99" y="589" font-size="11" fill="#52514e" class="f-ink2">92.7%</text><text x="141.22" y="609" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az-bytes</text><path d="M153.22,598 H618.99 A4,4 0 0 1 622.99,602 V608 A4,4 0 0 1 618.99,612 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="630.99" y="609" font-size="11" fill="#52514e" class="f-ink2">92.7%</text><text x="141.22" y="629" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">sql</text><path d="M153.22,618 H618.99 A4,4 0 0 1 622.99,622 V628 A4,4 0 0 1 618.99,632 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="630.99" y="629" font-size="11" fill="#52514e" class="f-ink2">92.7%</text><text x="141.22" y="649" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">object-store</text><path d="M153.22,638 H618.99 A4,4 0 0 1 622.99,642 V648 A4,4 0 0 1 618.99,652 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="630.99" y="649" font-size="11" fill="#52514e" class="f-ink2">92.7%</text><text x="16" y="677" font-size="11" fill="#0b0b0b" class="f-ink" font-weight="600">fanout-aggregate</text><text x="141.22" y="695" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><path d="M153.22,684 H540.97 A4,4 0 0 1 544.97,688 V694 A4,4 0 0 1 540.97,698 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="552.97" y="695" font-size="11" fill="#52514e" class="f-ink2">77.3%</text><text x="141.22" y="715" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><path d="M153.22,704 H540.97 A4,4 0 0 1 544.97,708 V714 A4,4 0 0 1 540.97,718 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="552.97" y="715" font-size="11" fill="#52514e" class="f-ink2">77.3%</text><text x="141.22" y="735" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">kv-edge</text><path d="M153.22,724 H538.14 A4,4 0 0 1 542.14,728 V734 A4,4 0 0 1 538.14,738 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="550.14" y="735" font-size="11" fill="#52514e" class="f-ink2">76.7%</text><text x="141.22" y="755" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">tiered mem+redis-az</text><path d="M153.22,744 H540.97 A4,4 0 0 1 544.97,748 V754 A4,4 0 0 1 540.97,758 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="552.97" y="755" font-size="11" fill="#52514e" class="f-ink2">77.3%</text><text x="141.22" y="775" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">tiered mem+kv-edge</text><path d="M153.22,764 H540.50 A4,4 0 0 1 544.50,768 V774 A4,4 0 0 1 540.50,778 H153.22 Z" fill="#2a78d6" class="f-s1"/><text x="552.50" y="775" font-size="11" fill="#52514e" class="f-ink2">77.2%</text><text x="153.22" y="799" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0%</text><text x="279.91" y="799" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">25%</text><text x="406.61" y="799" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">50%</text><text x="533.31" y="799" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">75%</text><text x="660" y="799" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100%</text><text x="153.22" y="815" font-size="10" fill="#898781" class="f-muted">origin-call reduction</text></svg>
</div>

## Latency, scenario by scenario

One chart per scenario: p50 through p99 for every configuration on a log axis, with the main-thread CPU spent per request next to each row. The bold **no cache** row is the workload without ocache; every row below it is the same workload running through one storage backend.

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 268" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>ssr-product-page latency</title><desc>Median (p50) and slowest-1% (p99) response latency for every configuration of ssr-product-page on a log scale, with main-thread CPU per request beside each row.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="268" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">SSR product page · ssr-product-page</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">40 KiB HTML, 2 DB queries + template render, 5k pages, Zipf head. Response latency for each configuration, from the</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">median (p50) to the slowest 1% of requests (p99).</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">p50</text><circle cx="71.14" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="81.14" y="80" font-size="11" fill="#52514e" class="f-ink2">p99</text><text x="788" y="80" font-size="10" fill="#898781" class="f-muted" text-anchor="end">cpu/req (ms)</text><line x1="124" y1="88" x2="124" y2="222" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="124" y="237" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="253" y1="88" x2="253" y2="222" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="253" y="237" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="382" y1="88" x2="382" y2="222" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="382" y="237" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="511" y1="88" x2="511" y2="222" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="511" y="237" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="640" y1="88" x2="640" y2="222" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="640" y="237" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1000</text><line x1="124" y1="222" x2="640" y2="222" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="124" y="253" font-size="10" fill="#898781" class="f-muted">latency in ms · log scale</text><text x="112" y="109" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">no cache</text><line x1="472.13" y1="105" x2="521.27" y2="105" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="472.13" cy="105" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="521.27" cy="105" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="530.27" y="109" font-size="11" fill="#52514e" class="f-ink2">120</text><text x="463.13" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">49.97</text><text x="788" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">13.432</text><text x="112" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><line x1="152.73" y1="131" x2="462.76" y2="131" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="152.73" cy="131" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="462.76" cy="131" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="471.76" y="135" font-size="11" fill="#52514e" class="f-ink2">42.27</text><text x="161.73" y="128" font-size="11" fill="#52514e" class="f-ink2">0.17</text><text x="788" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.531</text><text x="112" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><line x1="263.22" y1="157" x2="463.92" y2="157" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="263.22" cy="157" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="463.92" cy="157" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="472.92" y="161" font-size="11" fill="#52514e" class="f-ink2">43.16</text><text x="254.22" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.20</text><text x="788" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.490</text><text x="112" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az-bytes</text><line x1="262.75" y1="183" x2="463.99" y2="183" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="262.75" cy="183" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="463.99" cy="183" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="472.99" y="187" font-size="11" fill="#52514e" class="f-ink2">43.21</text><text x="253.75" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.19</text><text x="788" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.474</text><text x="112" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">kv-edge</text><line x1="371.01" y1="209" x2="481.98" y2="209" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="371.01" cy="209" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="481.98" cy="209" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="490.98" y="213" font-size="11" fill="#52514e" class="f-ink2">59.58</text><text x="362.01" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">8.22</text><text x="788" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.901</text></svg>
</div>

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 242" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>api-list latency</title><desc>Median (p50) and slowest-1% (p99) response latency for every configuration of api-list on a log scale, with main-thread CPU per request beside each row.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="242" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">JSON list API · api-list</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">8 KiB JSON, 3k query combinations, 40% of requests carry tracking params. Response latency for each configuration, from</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">the median (p50) to the slowest 1% of requests (p99).</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">p50</text><circle cx="71.14" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="81.14" y="80" font-size="11" fill="#52514e" class="f-ink2">p99</text><text x="788" y="80" font-size="10" fill="#898781" class="f-muted" text-anchor="end">cpu/req (ms)</text><line x1="124" y1="88" x2="124" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="124" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.01</text><line x1="253" y1="88" x2="253" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="253" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="382" y1="88" x2="382" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="382" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="511" y1="88" x2="511" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="511" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="640" y1="88" x2="640" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="640" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="124" y1="196" x2="640" y2="196" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="124" y="227" font-size="10" fill="#898781" class="f-muted">latency in ms · log scale</text><text x="112" y="109" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">no cache</text><line x1="574.56" y1="105" x2="630.51" y2="105" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="574.56" cy="105" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="630.51" cy="105" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="639.51" y="109" font-size="11" fill="#52514e" class="f-ink2">84.42</text><text x="565.56" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">31.10</text><text x="788" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.879</text><text x="112" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><line x1="252.55" y1="131" x2="592.28" y2="131" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="252.55" cy="131" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="592.28" cy="131" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="601.28" y="135" font-size="11" fill="#52514e" class="f-ink2">42.66</text><text x="243.55" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.10</text><text x="788" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.450</text><text x="112" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><line x1="373.34" y1="157" x2="593.29" y2="157" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="373.34" cy="157" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="593.29" cy="157" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="602.29" y="161" font-size="11" fill="#52514e" class="f-ink2">43.44</text><text x="364.34" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.86</text><text x="788" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.883</text><text x="112" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">kv-edge</text><line x1="490.86" y1="183" x2="608.94" y2="183" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="490.86" cy="183" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="608.94" cy="183" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="617.94" y="187" font-size="11" fill="#52514e" class="f-ink2">57.44</text><text x="481.86" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">6.98</text><text x="788" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.162</text></svg>
</div>

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 216" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>personalized-dashboard latency</title><desc>Median (p50) and slowest-1% (p99) response latency for every configuration of personalized-dashboard on a log scale, with main-thread CPU per request beside each row.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="216" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">Personalized dashboard · personalized-dashboard</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">15 KiB per-user page, 2k returning users plus 15% first-time sessions, tier cookie keyed. Response latency for each</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">configuration, from the median (p50) to the slowest 1% of requests (p99).</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">p50</text><circle cx="71.14" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="81.14" y="80" font-size="11" fill="#52514e" class="f-ink2">p99</text><text x="788" y="80" font-size="10" fill="#898781" class="f-muted" text-anchor="end">cpu/req (ms)</text><line x1="124" y1="88" x2="124" y2="170" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="124" y="185" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="253" y1="88" x2="253" y2="170" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="253" y="185" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="382" y1="88" x2="382" y2="170" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="382" y="185" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="511" y1="88" x2="511" y2="170" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="511" y="185" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="640" y1="88" x2="640" y2="170" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="640" y="185" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1000</text><line x1="124" y1="170" x2="640" y2="170" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="124" y="201" font-size="10" fill="#898781" class="f-muted">latency in ms · log scale</text><text x="112" y="109" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">no cache</text><line x1="478.17" y1="105" x2="533.83" y2="105" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="478.17" cy="105" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="533.83" cy="105" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="542.83" y="109" font-size="11" fill="#52514e" class="f-ink2">150</text><text x="469.17" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">55.65</text><text x="788" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.917</text><text x="112" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><line x1="138.36" y1="131" x2="510.58" y2="131" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="138.36" cy="131" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="510.58" cy="131" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="519.58" y="135" font-size="11" fill="#52514e" class="f-ink2">99.25</text><text x="147.36" y="128" font-size="11" fill="#52514e" class="f-ink2">0.13</text><text x="788" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.957</text><text x="112" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><line x1="264.06" y1="157" x2="511.18" y2="157" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="264.06" cy="157" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="511.18" cy="157" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="520.18" y="161" font-size="11" fill="#52514e" class="f-ink2">100</text><text x="255.06" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.22</text><text x="788" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.502</text></svg>
</div>

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 242" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>og-image latency</title><desc>Median (p50) and slowest-1% (p99) response latency for every configuration of og-image on a log scale, with main-thread CPU per request beside each row.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="242" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">OG image render · og-image</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">64 KiB PNG, 180 ms blocking render, 300 slugs, 30% conditional requests. Response latency for each configuration, from</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">the median (p50) to the slowest 1% of requests (p99).</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">p50</text><circle cx="71.14" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="81.14" y="80" font-size="11" fill="#52514e" class="f-ink2">p99</text><text x="788" y="80" font-size="10" fill="#898781" class="f-muted" text-anchor="end">cpu/req (ms)</text><line x1="124" y1="88" x2="124" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="124" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="227.20" y1="88" x2="227.20" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="227.20" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="330.40" y1="88" x2="330.40" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="330.40" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="433.60" y1="88" x2="433.60" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="433.60" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="536.80" y1="88" x2="536.80" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="536.80" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1000</text><line x1="640" y1="88" x2="640" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="640" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10000</text><line x1="124" y1="196" x2="640" y2="196" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="124" y="227" font-size="10" fill="#898781" class="f-muted">latency in ms · log scale</text><text x="112" y="109" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">no cache</text><line x1="492.19" y1="105" x2="546.04" y2="105" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="492.19" cy="105" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="546.04" cy="105" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="555.04" y="109" font-size="11" fill="#52514e" class="f-ink2">1229</text><text x="483.19" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">370</text><text x="788" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">182.089</text><text x="112" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><line x1="159.57" y1="131" x2="460.92" y2="131" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="159.57" cy="131" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="460.92" cy="131" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="469.92" y="135" font-size="11" fill="#52514e" class="f-ink2">184</text><text x="150.57" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.22</text><text x="788" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">8.058</text><text x="112" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><line x1="247.17" y1="157" x2="461.14" y2="157" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="247.17" cy="157" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="461.14" cy="157" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="470.14" y="161" font-size="11" fill="#52514e" class="f-ink2">185</text><text x="238.17" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.56</text><text x="788" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">8.989</text><text x="112" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az-bytes</text><line x1="240.04" y1="183" x2="461.07" y2="183" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="240.04" cy="183" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="461.07" cy="183" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="470.07" y="187" font-size="11" fill="#52514e" class="f-ink2">185</text><text x="231.04" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">1.33</text><text x="788" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">8.797</text></svg>
</div>

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 242" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>upstream-proxy latency</title><desc>Median (p50) and slowest-1% (p99) response latency for every configuration of upstream-proxy on a log scale, with main-thread CPU per request beside each row.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="242" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">Rate-limited upstream proxy · upstream-proxy</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">4 KiB JSON, 300 ms upstream capped at 10 concurrent calls, 20 keys. Response latency for each configuration, from the</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">median (p50) to the slowest 1% of requests (p99).</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">p50</text><circle cx="71.14" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="81.14" y="80" font-size="11" fill="#52514e" class="f-ink2">p99</text><text x="788" y="80" font-size="10" fill="#898781" class="f-muted" text-anchor="end">cpu/req (ms)</text><line x1="124" y1="88" x2="124" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="124" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="253" y1="88" x2="253" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="253" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="382" y1="88" x2="382" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="382" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="511" y1="88" x2="511" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="511" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="640" y1="88" x2="640" y2="196" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="640" y="211" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1000</text><line x1="124" y1="196" x2="640" y2="196" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="124" y="227" font-size="10" fill="#898781" class="f-muted">latency in ms · log scale</text><text x="112" y="109" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">no cache</text><line x1="576.70" y1="105" x2="631.87" y2="105" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="576.70" cy="105" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="631.87" cy="105" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="640.87" y="109" font-size="11" fill="#52514e" class="f-ink2">865</text><text x="567.70" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">323</text><text x="788" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">4.464</text><text x="112" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><line x1="160.79" y1="131" x2="191.56" y2="131" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="160.79" cy="131" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="191.56" cy="131" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="200.56" y="135" font-size="11" fill="#52514e" class="f-ink2">0.33</text><text x="151.79" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.19</text><text x="788" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.153</text><text x="112" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><line x1="241.16" y1="157" x2="310.41" y2="157" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="241.16" cy="157" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="310.41" cy="157" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="319.41" y="161" font-size="11" fill="#52514e" class="f-ink2">2.79</text><text x="232.16" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.81</text><text x="788" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.900</text><text x="112" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">object-store</text><line x1="442.64" y1="183" x2="512.27" y2="183" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="442.64" cy="183" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="512.27" cy="183" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="521.27" y="187" font-size="11" fill="#52514e" class="f-ink2">102</text><text x="433.64" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">29.52</text><text x="788" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.637</text></svg>
</div>

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 320" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>markdown-render latency</title><desc>Median (p50) and slowest-1% (p99) response latency for every configuration of markdown-render on a log scale, with main-thread CPU per request beside each row.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="320" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">Markdown render (function) · markdown-render</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">25 ms blocking render to 20 KiB HTML, 3k documents. Response latency for each configuration, from the median (p50) to</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">the slowest 1% of requests (p99).</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">p50</text><circle cx="71.14" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="81.14" y="80" font-size="11" fill="#52514e" class="f-ink2">p99</text><text x="788" y="80" font-size="10" fill="#898781" class="f-muted" text-anchor="end">cpu/req (ms)</text><line x1="124" y1="88" x2="124" y2="274" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="124" y="289" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.01</text><line x1="227.20" y1="88" x2="227.20" y2="274" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="227.20" y="289" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="330.40" y1="88" x2="330.40" y2="274" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="330.40" y="289" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="433.60" y1="88" x2="433.60" y2="274" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="433.60" y="289" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="536.80" y1="88" x2="536.80" y2="274" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="536.80" y="289" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="640" y1="88" x2="640" y2="274" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="640" y="289" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1000</text><line x1="124" y1="274" x2="640" y2="274" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="124" y="305" font-size="10" fill="#898781" class="f-muted">latency in ms · log scale</text><text x="112" y="109" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">no cache</text><line x1="536.84" y1="105" x2="616.81" y2="105" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="536.84" cy="105" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="616.81" cy="105" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="625.81" y="109" font-size="11" fill="#52514e" class="f-ink2">596</text><text x="527.84" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">100</text><text x="788" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">25.789</text><text x="112" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><line x1="209.05" y1="131" x2="474.95" y2="131" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="209.05" cy="131" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="474.95" cy="131" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="483.95" y="135" font-size="11" fill="#52514e" class="f-ink2">25.16</text><text x="200.05" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.07</text><text x="788" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.618</text><text x="112" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-local</text><line x1="268.76" y1="157" x2="475.55" y2="157" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="268.76" cy="157" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="475.55" cy="157" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="484.55" y="161" font-size="11" fill="#52514e" class="f-ink2">25.49</text><text x="259.76" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.25</text><text x="788" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.802</text><text x="112" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><line x1="324.34" y1="183" x2="476.94" y2="183" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="324.34" cy="183" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="476.94" cy="183" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="485.94" y="187" font-size="11" fill="#52514e" class="f-ink2">26.30</text><text x="315.34" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.87</text><text x="788" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">4.423</text><text x="112" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az-bytes</text><line x1="325.54" y1="209" x2="477.01" y2="209" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="325.54" cy="209" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="477.01" cy="209" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="486.01" y="213" font-size="11" fill="#52514e" class="f-ink2">26.34</text><text x="316.54" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.90</text><text x="788" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">4.478</text><text x="112" y="239" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">sql</text><line x1="372.46" y1="235" x2="481.40" y2="235" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="372.46" cy="235" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="481.40" cy="235" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="490.40" y="239" font-size="11" fill="#52514e" class="f-ink2">29.05</text><text x="363.46" y="239" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.56</text><text x="788" y="239" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">4.986</text><text x="112" y="265" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">object-store</text><line x1="486.58" y1="261" x2="542.40" y2="261" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="486.58" cy="261" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="542.40" cy="261" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="551.40" y="265" font-size="11" fill="#52514e" class="f-ink2">113</text><text x="477.58" y="265" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">32.61</text><text x="788" y="265" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">5.002</text></svg>
</div>

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 294" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>fanout-aggregate latency</title><desc>Median (p50) and slowest-1% (p99) response latency for every configuration of fanout-aggregate on a log scale, with main-thread CPU per request beside each row.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="294" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">Fan-out aggregation (function) · fanout-aggregate</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">3 parallel upstreams, 220 ms slowest, 500 keys, SWR with a long stale window. Response latency for each configuration,</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">from the median (p50) to the slowest 1% of requests (p99).</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">p50</text><circle cx="71.14" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="81.14" y="80" font-size="11" fill="#52514e" class="f-ink2">p99</text><text x="788" y="80" font-size="10" fill="#898781" class="f-muted" text-anchor="end">cpu/req (ms)</text><line x1="153.22" y1="88" x2="153.22" y2="248" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="153.22" y="263" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.01</text><line x1="250.58" y1="88" x2="250.58" y2="248" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="250.58" y="263" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0.1</text><line x1="347.93" y1="88" x2="347.93" y2="248" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="347.93" y="263" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1</text><line x1="445.29" y1="88" x2="445.29" y2="248" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="445.29" y="263" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="542.64" y1="88" x2="542.64" y2="248" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="542.64" y="263" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">100</text><line x1="640" y1="88" x2="640" y2="248" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="640" y="263" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">1000</text><line x1="153.22" y1="248" x2="640" y2="248" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="153.22" y="279" font-size="10" fill="#898781" class="f-muted">latency in ms · log scale</text><text x="141.22" y="109" font-size="11" fill="#0b0b0b" class="f-ink" text-anchor="end" font-weight="600">no cache</text><line x1="592.13" y1="105" x2="629.81" y2="105" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="592.13" cy="105" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="629.81" cy="105" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="638.81" y="109" font-size="11" fill="#52514e" class="f-ink2">786</text><text x="583.13" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">322</text><text x="788" y="109" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">6.537</text><text x="141.22" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">memory</text><line x1="219.23" y1="131" x2="606.26" y2="131" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="219.23" cy="131" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="606.26" cy="131" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="615.26" y="135" font-size="11" fill="#52514e" class="f-ink2">450</text><text x="210.23" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.05</text><text x="788" y="135" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.903</text><text x="141.22" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">redis-az</text><line x1="336.76" y1="157" x2="606.43" y2="157" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="336.76" cy="157" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="606.43" cy="157" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="615.43" y="161" font-size="11" fill="#52514e" class="f-ink2">452</text><text x="327.76" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.77</text><text x="788" y="161" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.605</text><text x="141.22" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">kv-edge</text><line x1="428.66" y1="183" x2="607.28" y2="183" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="428.66" cy="183" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="607.28" cy="183" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="616.28" y="187" font-size="11" fill="#52514e" class="f-ink2">461</text><text x="419.66" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">6.75</text><text x="788" y="187" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">4.239</text><text x="141.22" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">tiered mem+redis-az</text><line x1="223.06" y1="209" x2="606.38" y2="209" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="223.06" cy="209" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="606.38" cy="209" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="615.38" y="213" font-size="11" fill="#52514e" class="f-ink2">452</text><text x="214.06" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.05</text><text x="788" y="213" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">2.987</text><text x="141.22" y="239" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">tiered mem+kv-edge</text><line x1="221.98" y1="235" x2="607.24" y2="235" stroke="#e1e0d9" class="k-grid" stroke-width="2"/><circle cx="221.98" cy="235" r="4.5" fill="#2a78d6" stroke="#fcfcfb" class="f-s1 k-surface" stroke-width="2"/><circle cx="607.24" cy="235" r="4.5" fill="#eb6834" stroke="#fcfcfb" class="f-s2 k-surface" stroke-width="2"/><text x="616.24" y="239" font-size="11" fill="#52514e" class="f-ink2">461</text><text x="212.98" y="239" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">0.05</text><text x="788" y="239" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">3.015</text></svg>
</div>

## More capacity, not just lower latency

A cache hit skips whatever work the origin would have done on the main thread — and that work is what limits how much traffic one server instance can handle. In the heaviest scenario here, `og-image`, main-thread CPU drops from 182.089 ms per request to 8.058 ms. When the origin mostly waits on I/O instead, the same hit buys latency but very little capacity — the CPU column in the charts above shows which case you are in.

## What a cache hit costs

Serving from cache is not free: ocache has to hash a key, check the entry is still valid, decode it, and build a `Response`. Measured against in-memory storage with nothing else running, a hit adds 7.8 to 29.8 µs for a cached handler and 4.1 to 4.5 µs for a cached function, across payloads from 4 KiB to 64 KiB.

| payload | handler direct (µs) | handler cached (µs) | handler adds (µs) | function adds (µs) |
| ------: | ------------------: | ------------------: | ----------------: | -----------------: |
|   4 KiB |                35.8 |                55.2 |         **+19.5** |           **+4.3** |
|   6 KiB |                37.9 |                58.9 |         **+21.0** |           **+4.5** |
|   8 KiB |                51.0 |                58.8 |          **+7.8** |           **+4.3** |
|  15 KiB |                52.4 |                81.0 |         **+28.6** |           **+4.1** |
|  20 KiB |                56.6 |                81.7 |         **+25.1** |           **+4.5** |
|  40 KiB |                92.3 |               114.2 |         **+21.9** |           **+4.2** |
|  64 KiB |               119.7 |               149.5 |         **+29.8** |           **+4.2** |

<div style="max-width:100%;overflow-x:auto">
<svg style="width:100%;height:auto;max-width:800px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 404" font-family="system-ui, -apple-system, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif" role="img" class="ocache-chart"><title>Hit-path cost</title><desc>Extra microseconds a cache hit adds per call, cached handler versus cached function, across payload sizes.</desc><style>svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@media (prefers-color-scheme:dark){svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}}[data-theme="dark"] svg.ocache-chart,.dark svg.ocache-chart{--surface:var(--ocache-chart-surface,#1a1a19);--ink:var(--ocache-chart-ink,#ffffff);--ink2:var(--ocache-chart-ink-2,#c3c2b7);--muted:#898781;--grid:#2c2c2a;--axis:#383835;--s1:#3987e5;--s2:#d95926;--deemph:#6e6c67}[data-theme="light"] svg.ocache-chart,.light svg.ocache-chart{--surface:var(--ocache-chart-surface,#fcfcfb);--ink:var(--ocache-chart-ink,#0b0b0b);--ink2:var(--ocache-chart-ink-2,#52514e);--muted:#898781;--grid:#e1e0d9;--axis:#c3c2b7;--s1:#2a78d6;--s2:#eb6834;--deemph:#a9a7a0}@supports (--ocache:0){.ocache-chart .f-surface{fill:var(--surface)}.ocache-chart .f-ink{fill:var(--ink)}.ocache-chart .f-ink2{fill:var(--ink2)}.ocache-chart .f-muted{fill:var(--muted)}.ocache-chart .f-grid{fill:var(--grid)}.ocache-chart .f-axis{fill:var(--axis)}.ocache-chart .f-s1{fill:var(--s1)}.ocache-chart .f-s2{fill:var(--s2)}.ocache-chart .f-deemph{fill:var(--deemph)}.ocache-chart .k-surface{stroke:var(--surface)}.ocache-chart .k-grid{stroke:var(--grid)}.ocache-chart .k-axis{stroke:var(--axis)}}</style><rect width="800" height="404" fill="#fcfcfb" class="f-surface"/><text x="16" y="26" font-size="15" fill="#0b0b0b" class="f-ink" font-weight="600">Hit-path cost</text><text x="16" y="42" font-size="11" fill="#52514e" class="f-ink2">Extra microseconds a cache hit costs compared to calling the origin directly: hashing the key, validating and decoding</text><text x="16" y="58" font-size="11" fill="#52514e" class="f-ink2">the entry, and — for handlers — building a Response. Measured against in-memory storage with nothing else running.</text><circle cx="20" cy="76" r="4" fill="#2a78d6" class="f-s1"/><text x="30" y="80" font-size="11" fill="#52514e" class="f-ink2">handler</text><circle cx="96.66" cy="76" r="4" fill="#eb6834" class="f-s2"/><text x="106.66" y="80" font-size="11" fill="#52514e" class="f-ink2">function</text><line x1="96" y1="88" x2="96" y2="358" stroke="#c3c2b7" class="k-axis" stroke-width="1"/><text x="96" y="373" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">0</text><line x1="284" y1="88" x2="284" y2="358" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="284" y="373" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">10</text><line x1="472" y1="88" x2="472" y2="358" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="472" y="373" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">20</text><line x1="660" y1="88" x2="660" y2="358" stroke="#e1e0d9" class="k-grid" stroke-width="1"/><text x="660" y="373" font-size="10" fill="#898781" class="f-muted" text-anchor="middle">30</text><text x="96" y="389" font-size="10" fill="#898781" class="f-muted">microseconds added per hit</text><text x="84" y="114" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">4 KiB</text><path d="M96,96 H458.18 A4,4 0 0 1 462.18,100 V104 A4,4 0 0 1 458.18,108 H96 Z" fill="#2a78d6" class="f-s1"/><text x="470.18" y="106" font-size="10" fill="#52514e" class="f-ink2">19.5 us</text><path d="M96,110 H172.79 A4,4 0 0 1 176.79,114 V118 A4,4 0 0 1 172.79,122 H96 Z" fill="#eb6834" class="f-s2"/><text x="184.79" y="120" font-size="10" fill="#52514e" class="f-ink2">4.3 us</text><text x="84" y="152" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">6 KiB</text><path d="M96,134 H486.64 A4,4 0 0 1 490.64,138 V142 A4,4 0 0 1 486.64,146 H96 Z" fill="#2a78d6" class="f-s1"/><text x="498.64" y="144" font-size="10" fill="#52514e" class="f-ink2">21.0 us</text><path d="M96,148 H176.95 A4,4 0 0 1 180.95,152 V156 A4,4 0 0 1 176.95,160 H96 Z" fill="#eb6834" class="f-s2"/><text x="188.95" y="158" font-size="10" fill="#52514e" class="f-ink2">4.5 us</text><text x="84" y="190" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">8 KiB</text><path d="M96,172 H239.22 A4,4 0 0 1 243.22,176 V180 A4,4 0 0 1 239.22,184 H96 Z" fill="#2a78d6" class="f-s1"/><text x="251.22" y="182" font-size="10" fill="#52514e" class="f-ink2">7.8 us</text><path d="M96,186 H172.52 A4,4 0 0 1 176.52,190 V194 A4,4 0 0 1 172.52,198 H96 Z" fill="#eb6834" class="f-s2"/><text x="184.52" y="196" font-size="10" fill="#52514e" class="f-ink2">4.3 us</text><text x="84" y="228" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">15 KiB</text><path d="M96,210 H629.97 A4,4 0 0 1 633.97,214 V218 A4,4 0 0 1 629.97,222 H96 Z" fill="#2a78d6" class="f-s1"/><text x="641.97" y="220" font-size="10" fill="#52514e" class="f-ink2">28.6 us</text><path d="M96,224 H169.11 A4,4 0 0 1 173.11,228 V232 A4,4 0 0 1 169.11,236 H96 Z" fill="#eb6834" class="f-s2"/><text x="181.11" y="234" font-size="10" fill="#52514e" class="f-ink2">4.1 us</text><text x="84" y="266" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">20 KiB</text><path d="M96,248 H563.21 A4,4 0 0 1 567.21,252 V256 A4,4 0 0 1 563.21,260 H96 Z" fill="#2a78d6" class="f-s1"/><text x="575.21" y="258" font-size="10" fill="#52514e" class="f-ink2">25.1 us</text><path d="M96,262 H175.86 A4,4 0 0 1 179.86,266 V270 A4,4 0 0 1 175.86,274 H96 Z" fill="#eb6834" class="f-s2"/><text x="187.86" y="272" font-size="10" fill="#52514e" class="f-ink2">4.5 us</text><text x="84" y="304" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">40 KiB</text><path d="M96,286 H503.98 A4,4 0 0 1 507.98,290 V294 A4,4 0 0 1 503.98,298 H96 Z" fill="#2a78d6" class="f-s1"/><text x="515.98" y="296" font-size="10" fill="#52514e" class="f-ink2">21.9 us</text><path d="M96,300 H170.34 A4,4 0 0 1 174.34,304 V308 A4,4 0 0 1 170.34,312 H96 Z" fill="#eb6834" class="f-s2"/><text x="182.34" y="310" font-size="10" fill="#52514e" class="f-ink2">4.2 us</text><text x="84" y="342" font-size="11" fill="#52514e" class="f-ink2" text-anchor="end">64 KiB</text><path d="M96,324 H652.51 A4,4 0 0 1 656.51,328 V332 A4,4 0 0 1 652.51,336 H96 Z" fill="#2a78d6" class="f-s1"/><text x="664.51" y="334" font-size="10" fill="#52514e" class="f-ink2">29.8 us</text><path d="M96,338 H171.11 A4,4 0 0 1 175.11,342 V346 A4,4 0 0 1 171.11,350 H96 Z" fill="#eb6834" class="f-s2"/><text x="183.11" y="348" font-size="10" fill="#52514e" class="f-ink2">4.2 us</text></svg>
</div>

Notice the cost does not grow with payload size — nothing on the hit path copies the body, so the variation between rows is per-call work and measurement noise, not a size effect. The handler path costs several times the function path, and that gap is the price of being a real HTTP cache instead of a simple memo table: deriving a key from the request, validating the entry, merging headers, and building a `Response` on every call.

## When caching is not worth it

A hit is never free, and neither is the storage read that finds it: caching trades a trip to your origin for a trip to your storage backend. Adding the largest measured hit-path overhead (0.03 ms) to each backend's median read time gives the break-even point — the minimum origin cost a handler needs before caching pays off at all.

| backend          | read p50 (ms) | read p99 (ms) | a handler pays off above (ms) | models                                                  |
| ---------------- | ------------: | ------------: | ----------------------------: | ------------------------------------------------------- |
| `memory`         |             0 |             0 |                          0.03 | in-process Map (createMemoryStorage)                    |
| `redis-local`    |          0.12 |           0.5 |                          0.15 | unix socket or sidecar valkey                           |
| `redis-az`       |           0.6 |             3 |                          0.63 | same-region TCP                                         |
| `redis-az-bytes` |           0.6 |             3 |                          0.63 | same-region TCP, one blob per entry (createBlobStorage) |
| `sql`            |             2 |            15 |                          2.03 | Postgres or D1 key-value table                          |
| `kv-edge`        |             6 |            40 |                          6.03 | Cloudflare KV / Deno KV, eventually consistent          |
| `object-store`   |            30 |           120 |                         30.03 | S3 / R2 GetObject                                       |

If your handler is faster than its row, it is faster with no cache at all. Two things raise the bar further: a **low hit ratio**, because every miss pays for a storage read that found nothing, and a **remote backend**, which also has to decode the response body on your thread — that part _does_ grow with payload size, and this table does not include it.

> [!TIP]
> The storage profiles are estimates fitted to a published p50/p99 pair, not measurements of your backend. They live in one table in [`bench/harness/storage.ts`](https://github.com/unjs/ocache/blob/main/bench/harness/storage.ts) — measure your own backend and edit it before quoting any of these numbers.

## Reproducing this page

```sh
pnpm bench --json=bench/results/steady.json --md=bench/results/steady.md
pnpm bench:docs bench/results/steady.json
```

The first command runs every scenario and writes the full report, including the tables this page summarizes. The second renders the charts, inlines them, and regenerates this page from the same JSON — the charts are part of the page, not files next to it. (`pnpm bench:chart` writes them out as standalone SVGs if you want them separately.) The prose lives in `bench/docs.md`; the numbers never do.
