What the platform delivers
Real Cloudflare deployment (§2.2 of the report) — p50 unless noted, from one host over one ISP uplink to a Cloudflare-assigned DO region. Each card: the measured number, and what it lets you build.
3–35msCall to a co-located objectvs 450–692 ms when the object is on the far side of the worldWhere you put the object is the biggest single effect measured here — bigger than everything else on this page combined. Put it near its users.
4,727/sAggregate appends · 32 Log DOs≈25× a single object's rate · measured, not inferredHorizontal scale is real — adding objects adds capacity, with no shared bottleneck between them.
1,022Concurrent WS on one DOstill serving traffic at the peak · refused at a configured capMany clients per object — and the limit is a setting you control, not resource exhaustion.
+28msDurable write, above the networkpaired measurement · 0/200 negative pairsPersist authoritative state in about one round-trip — durable storage co-located with the object.
+3msRouted RPC, above the networka call into a peer client, no durable writeRouting through the mesh is nearly free — agents and UIs feel instant.
0err10 minutes sustainedp50 36.4 → 37.1 ms across 12,000 mixed opsIt stays that way — no drift, no leak, no eviction cliff under steady load.
0%Conflicts, atomic counter16 writers, one key · final exact · vs 85% for CASCheap counters & ledgers that stay exact under contention — cost scales with useful work, not retries.
50kEntries replayed after a dropgap-free in 17.3 s · 100 entries in 15 msA client that disconnects loses nothing — and you know what a deep catch-up costs before you design for it.
~0.5sCold DO first touchone-time wake; every call after is warmFirst hit on a sleeping object pays a wake — mask it with a "waking…" affordance.
~0Standing cost at restidle objects hibernateCheap to operate — you pay for active work, not for objects sitting idle.
On latency numbers: this benchmark runs from a single host on one
uplink, and round-trip-dominated latencies varied 67–123% between repetitions of identical
code. So the figures above are the ones that survive that: throughput, the
paired server-side cost of an operation, and structural limits. Raw latency medians are in
the full report, with their spread beside them.
Latency & throughput
Real Cloudflare (§2.2). All latencies in milliseconds.
Geography — routed-call p50 (ms), by client region × object region
| client ↓ / object → | N. America W | N. America E | Europe W | Europe N | Asia-Pacific | Oceania |
| N. America W (San Jose) | 14 | 159 | 291 | 348 | 224 | 330 |
| N. America E (Miami) | 180 | 5 | 226 | 286 | 350 | 451 |
| Europe W (Paris) | 299 | 221 | 9 | 74 | 449 | 665 |
| Europe N (Stockholm) | 352 | 284 | 74 | 13 | 501 | 680 |
| Asia-Pacific (Osaka) | 230 | 346 | 462 | 502 | 3 | 264 |
| Oceania (Sydney) | 307 | 425 | 608 | 681 | 217 | 30 |
What it means: a call to a co-located object costs 3–35 ms; the same call to an object on the far side of the world costs 450–692 ms. Where you put the object is the largest single effect in this entire benchmark — bigger than the durable-write cost (+28 ms), the saturation knee, and fan-out combined. Because every workspace, log and doc is its own object, that placement is a per-tenant decision, and Cloudflare makes it wherever the object is first touched — so it is worth being deliberate about. Halve these figures for one-way distance: a routed call crosses to the object and back twice.
Measured by running the shipped client from a probe pinned to each region against an object placed in each region — all 9×9 combinations (6 shown; the full matrix and the two regions that collapsed onto one datacentre are in the report). Placement is not assumed: it is validated by requiring the diagonal to be the minimum of its column, which held for every distinct location. Both ends are inside Cloudflare, so this is region-to-region cost, not an end-user's last mile.
Horizontal scale — the same load against N independent objects at once
| objects | Log appends/s (aggregate) | per object | Doc commits/s (aggregate) | per object |
| 1 | 187 | 187 | 208 | 208 |
| 4 | 631 | 158 | 731 | 183 |
| 8 | 1,268 | 159 | 1,309 | 164 |
| 16 | 2,492 | 156 | 2,562 | 160 |
| 32 | 4,727 | 148 | 4,478 | 140 |
What it means: per-object throughput stays nearly flat as objects are added, so 32 objects do ~25× the work of one. This is the sharding claim measured rather than argued — it was previously printed as "∞" with no data behind it. It is not perfectly linear: about 21% of per-object efficiency is lost by 32 objects. A client-side event-loop-lag control ran throughout (~2 ms), confirming the benchmark client was never the limit.
Cost of an operation — above the network, measured by pairing
| operation | median op | median floor | server's share | negative pairs |
| routed RPC call (no durable write) | 14.8 | 11.2 | +3.2 | 34/200 |
| durable Log append | 39.6 | 11.2 | +28.3 | 0/200 |
What it means: routing a call through the mesh into a peer costs ~3 ms of server work; a durable commit costs ~28 ms. The "negative pairs" column is the honesty check — a DO-backed call cannot really be faster than a Worker-only one, so that fraction bounds the jitter still inside each pair. Zero of them for the durable write means that figure is cleanly resolved.
RPC round-trip — a call routed into a peer client (no durable write)
| scenario | median | range across 6 runs | throughput |
| call noop (serial) | 18.0 | 12.0 – 34.1 | — |
| call echo-1KB (serial) | 17.6 | 14.1 – 33.7 | — |
| call noop (concurrent, 32 in-flight) | 51.5 | 42.9 – 62.0 | 589 calls/s |
What it means: a routed call is ≈ one network round-trip plus ~3 ms of server work. The wide ranges are this host's uplink, not the platform — which is exactly why the paired table above is the figure to design against.
Concurrency — where one socket saturates
| in flight | 1 | 8 | 16 | 32 | 64 | 128 | 256 |
| throughput | 63/s | 317/s | 369/s | 460/s | 726/s | 711/s | 934/s |
| p50 latency | 14.8 | 24.4 | 38.1 | 65.3 | 82.6 | 176.0 | 268.7 |
What it means: throughput climbs steeply to about 64 in flight, then flattens while latency keeps rising roughly linearly. Past the knee you are buying queue depth, not throughput — add sockets or objects instead.
Log — one Log DO; append = a durable SQLite commit
| scenario | n | p50 | p95 | p99 | throughput |
| append (serial) | median of 6 | 40.0 | range 37.9 – 44.5 | — |
| append (concurrent, 32) | median of 6 | — | range 452 – 517/s | 488 appends/s |
| live-tail delivery (append→deliver) | median of 6 | 39.1 | range 37.1 – 44.9 | — |
| read pagination (100/page, 1000) | 10 pages | 124.7 | 343 | 343 | 591 entries/s |
| subscribe replay (recent 200) | 200 | 19.5 ms total | 10,264 entries/s |
What it means: ~488 durable appends/s per log carries a busy chat or event stream, and sharding across logs multiplies it (see the scale table). Subscribe-replay re-sends a recent window in ~20 ms so a reconnecting client catches up gap-free.
Replay depth & the cold tier — what a client that was away a long time pays
| entries to replay | 100 | 1,000 | 10,000 | 50,000 |
| time | 15 ms | 213 ms | 2.75 s | 17.3 s |
| completed gap-free | ✓ | ✓ | ✓ | ✓ |
What it means: every depth replayed completely — a client away for 50,000 entries still loses nothing, and now you know it takes ~17 s, so you can show progress instead of appearing to hang. Entries older than the hot threshold live in R2 cold segments, and reading across that boundary was no slower than reading the hot tail (104 vs 125 ms/page) — the tier split is not a latency cliff.
Doc — one Doc DO; durable conditional + atomic writes
| scenario | commits | p50 | p95 | throughput | integrity |
| CAS serial (uncontended conditional write) | median of 6 | 38.5 | range 32.5–42.6 | — | — |
| CAS contended (16 conns racing on one key) | 800 | — | — | 21 commits/s | 85% conflicts · final exact (800) |
| atomic incr (16 conns racing on one counter) | 800 | — | — | 283 commits/s | 0% conflicts · 1.0× amplification · final exact |
What it means: the single-writer DO never loses an update; a server-side atomic incr commits a counter/ledger in one round-trip with no retry storm — so cheap, exact counters and balances whose cost scales with useful commits, not with contention.
Connections, presence & cold start
| metric | p50 | p95 | p99 / max | note |
| WS connect (warm DO) | 63.8 | range 51.6 – 86.0 across 6 runs | flat while holding ~1,000 connections |
| Max concurrent WS on one DO | 1,022 held · 1,019 still alive · 20/20 routed calls served | refused with close 1013 at a configured cap of 1,024 |
| Cold Log DO (first-ever dial) | 557 | 681 | 681 | instantiation + schema init + handshake |
| Cold workspace DO (fresh ws) | 508 | 627 | 627 | one-time wake; every call after is warm |
What it means: one object holds 1,022 live connections and still serves traffic, with connect latency flat the whole way up — and the wall it hits is DEFAULT_MAX_CONNS_PER_WORKSPACE, a deliberate DoS control you can raise, not resource exhaustion. The previous "≥200, ceiling not reached" was the harness's own configured target, not a limit.
Presence fan-out — propagation vs number of subscribers
| subscribers | 1 | 3 | 10 | 50 | 200 |
| p50 propagation | 59.4 | 48.8 | 61.9 | 78.4 | 129.8 |
What it means: presence reaches a handful of subscribers in about one round-trip, but fan-out is not free at width — 200 subscribers takes ~2.7× as long as 10. An earlier edition of this page said there was no fan-out cost; that was generalised from a 3-subscriber sample, a width at which the cost cannot show up.
Payload limits — how big a routed call can be
| payload | 1 KB | 16 KB | 64 KB | 256 KB | 512 KB | 1 MiB |
| p50 | 16.2 | 20.9 | 33.8 | 44.3 | 64.9 | refused |
What it means: cost is flat to ~16 KB then tracks bytes; 512 KB is the largest usable payload. At 1 MiB the server rejects the frame before parsing it (close 1009) — a deliberate control, since an unbounded frame is cheap memory amplification against a single-threaded shard. Bulk bytes belong on the artifact plane below.
Artifacts — bulk bytes to R2
| path | result | note |
| direct-to-R2 multipart (64 MB, 8×8 MB) | completes · ✓ byte-verified | ≈10.5 MB/s aggregate · 0 errors · 0 dangling MPUs |
| binding plane upload (8 MB, through the Worker) | ≈9.8 MB/s from one host | client-uplink-bound; fine for small/medium blobs |
| binding plane download (8 MB) | ≈22.3 MB/s | — |
What it means: large files upload direct edge↔R2 (bytes never touch billable DO time) and round-trip byte-for-byte; small/medium blobs stream simply through the Worker.