Repository navigation
Durable Object reactivation stalls 3–28s before JS RPC handler (minimal repro + traces) #8010
Description
Summary
On hosted Cloudflare Workers, a minimal SQLite-backed Durable Object intermittently waits 3–28 seconds before its JavaScript RPC handler begins. One captured call took 27,844 ms at the caller / 27,888 ms at the HTTP client; the target native invocation reported 27,830 ms wall time and 0 ms CPU. The handler does only a synchronous read of one never-written key and returns diagnostic fields.
Reproduction and exported traces: https://github.com/acchou/cloudflare-do-activation-repro
This is a hosted-platform report; I have not reproduced the delay in local workerd. I am filing here because the observed boundary is Durable Object RPC/activation, with related context in #7607. I do not know the internal cause.
Minimal reproduction
Pinned Worker source. The repo contains the measured Worker logic, a standalone idle/repeat runner, and sanitized synthetic evidence. No application service bindings, user data, external database, AI, or billing code are involved.
npm ci
npm run check
npm test
npx wrangler login
npm run setup
npm run deploy
npm run probe -- --objects-per-hint 6 --cycles 10 --idle-ms 25000
npm run cleanupThe path is HTTP Worker → Caller DO → Target DO. Target.ping() reads ctx.storage.kv.get('never-written') and returns entry time, instance UUID, isolate UUID, sequence and object ID. There are no application writes, timers, external requests, or initialization tasks in that handler. A separate location probe runs outside the measured ping.
The runner uses fresh object identities with auto, wnam, enam and weur hints, rotates callers, leaves objects idle, then pairs each first call with an immediate repeat. The failure is intermittent and identity-dependent; a fresh deployment is not guaranteed to hit a slow placement.
Expected / actual
Expected: after ordinary routing and activation overhead, this minimal handler should return promptly.
Actual: the caller and HTTP client occasionally wait seconds before handler entry. In the recorded study, all 18 calls over one second were first pings on their in-memory object instances. The 1,600 later pings peaked at 583 ms. An object can reactivate in an already-observed JS isolate, so this is not necessarily a full isolate cold start.
A fresh enam replacement placed in ORD subsequently stalled on five of six controlled reopens (3,726–16,925 ms), while its immediate repeats were all ≤83 ms. A newly created caller in DFW also hit the ORD delay. The original IAD object later recovered without changing identity. Renaming therefore did not reliably solve this case.
Trace evidence
Measured 2026-10-26 20:24:17.963–20:31:43.270 UTC, paid Workers account, compatibility date 2026-04-09, Wrangler 4.151.1. Worker codex-placement-446b6c, version 0c5183b4-c380-4983-bf82-15e3274012ba. The temporary Worker and its namespaces have since been deleted. Account ID can be supplied privately if required.
| Trace ID | Path | Awaited RPC | Relevant timing |
|---|---|---|---|
3612b97993290a98b4b86358d61b68d1 |
SJC → ORD | 27,844 ms | Target native wall 27,830 ms, CPU 0 ms; handler starts at the end |
1c7b4d4cef630ccb622c22de9f3719b7 |
LAX → ORD | 7,566 ms | Target native invocation 7,479 ms, almost entirely before JS handler |
5e02221d0a74158bdc23d02dd212ce3d |
SJC → IAD | 11,875 ms | Target native invocation only 2 ms; delay occurs earlier in dispatch |
For the 27.844-second example:
- Caller dispatch: 20:27:02.142 UTC.
- Target handler entry: 20:27:29.957 UTC.
- Target object:
f5547a44420b5abe411ba3c4e47654228210248ad98afc31ad68338d03a11c4b. - Caller object:
d38dbb929e143dc96ead34f507eb4dce8ef1e37182c9e051c2c7407f4a553fe5. - Probe ID:
efd651f2-6ae1-44bc-90e5-2b2d2c2ec08b.
The evidence directory contains all 2,016 synthetic probe records and four compact trace exports retaining native span relationships/timestamps. Native spans corroborated the self-reported locations of all 72 targets across 15 colos. The exports omit account identifiers, credentials, IP addresses and unrelated logs.
Interpretation / question
The independent HTTP and caller timings confirm a real stall, not just a long-lived completed trace span. Cross-host entry-time subtraction is supporting evidence; I rely primarily on those same-process durations and native spans. The data locates waits before application work but does not identify storage activation, scheduling, routing, or a physical host issue.
Unlike #7607's reported delays on running objects, this sample's long delays occur on object reactivation. Could Cloudflare inspect the saved object IDs/timestamps for activation or RPC dispatch delays, and advise whether this belongs to the same platform issue or a separate one?
Activity
acchou commentedon Oct 26, 2026
Concurrency follow-up: additional requests also wait
I tested what happens when more requests are sent to the same target while its first RPC is stalled. Full results and reproduction instructions, all request records, and grouped comparisons are now published.
Result: 11 stalls across 832 primary calls, with all 33 follow-up requests waiting until the original target handler began. The stalls affected three objects and ranged from 1,180 to 9,913 ms. In every group, all four handlers entered in the same recorded millisecond on the same object ID and instance UUID, with sequence numbers 1–4. No follow-up bypassed the wait.
Method
Fresh temporary deployment; 64 target identities split evenly between auto/wnam/enam/weur, eight warmed callers, initial access plus twelve rounds after 25 seconds idle. At most four primary groups ran concurrently. When a primary remained pending after one second, the driver sent:
Actual server-side dispatch timestamps confirm every follow-up was sent before the original target handler entered. All 873 HTTP requests succeeded (832 primary + 33 follow-ups + 8 warm-ups). The target handler is unchanged from the original report. Runnable driver; use
npm run concurrencyafter setup/deploy.Longest example
Original dispatch: 2026-10-26 20:45:47.279 UTC. All four target handlers entered at 20:45:57.183 UTC.
09bcac9064d49073019c70a4adb3cddc11d4821383ff05a97a5c879941ec776f.7b1a330b-2722-4772-8c9d-06a193f036b3.cc85086d038328fc95703a8d624d54a6: target recorded 0 ms CPU, 8,865 ms native wall time; its native invocation started after the follow-ups, with 8,843 ms before JavaScript handler entry.These measurements are consistent with a shared wait before target execution, rather than only the original caller being delayed. They do not identify the internal cause. Sending follow-ups could affect activation timing, so this is not a counterfactual measurement of how long the original would have waited alone. Unlike some duplicates in #7607, none here entered ahead of the original.
The temporary Worker
do-activation-d5f54eab08f7(versionab14e375-2df7-4ab8-b852-34db63dcd6fb) was deleted after this run. The public exports omit account identifiers, credentials, IP addresses and request headers. Eight evidence/packaging checks and the typecheck pass.Could you check whether the shared pre-handler wait across independent callers narrows down the activation/dispatch mechanism involved?
danlapid commentedon Oct 27, 2026
Just following up that while I don't have an answer yet, the team is actively taking a look and investigating.