Packing always-awake Durable Objects into Containers to cut duration cost
Robert Chandler (@bertie_ai) says keeping 1,000 Durable Objects awake costs $4,050 a month, and that he ran the same 1,000 for $22 a month by pooling them inside Containers with workerd; the thread covers why, the durability trade-off and when real Durable Objects are still cheaper. The figures are the author’s calculations, not a bill.
- Products
- Durable ObjectsContainersR2
- Source
- Author experience𝕏
- Author
- Robert Chandler (@bertie_ai)
Key points
- The author says Cloudflare bills every awake Durable Object as if it uses 128 MB of memory, while in workerd, Cloudflare’s open-source runtime, each of his objects used about 200 KB. He therefore packed the objects into containers running workerd, autoscaling from 1 to 5 containers for 6,000 WebSockets, and moved objects between containers mid-write with no writes lost.
- He names the trade-off: a real Durable Object does not acknowledge a write until it is replicated, while in his pool a container crash can lose up to 30 seconds of writes. He considers that acceptable for cursors, presence, game state and agent scratchpads, and says to keep real Durable Objects for anything involving money.
- He adds that if your objects mostly sleep, real Durable Objects are cheaper anyway; by his numbers pooling only wins once objects are awake more than about 2 hours a month. The repository README likewise says objects that mostly hibernate should stay real Durable Objects, and that checkpoints are written as one R2 segment per node every 30 seconds rather than one PUT per object, because per-object PUTs would cost more than the container.
- His most useful finding, in his words: the official containers library relayed every WebSocket frame through JavaScript, topped out around 1,000 messages per second and billed each one; a one-line passthrough fixed it. He says the whole Cloudflare bill for all the testing was $0.63.
- Official docs (rechecked 2026-10-16): Durable Objects duration is billed for the 128 MB allocated regardless of actual usage, even when several objects share one isolate; idle objects eligible for hibernation are not billed for duration; calling accept() on a WebSocket bills duration for the whole connection, so the WebSocket Hibernation API is recommended. Containers are billed per 10 ms while active, with memory and disk charged on the provisioned instance size.
Original sources
Published
Original post
Read on 𝕏Robert Chandler (@bertie_ai) says keeping 1,000 Durable Objects awake costs $4,050 a month, and that he ran the same 1,000 for $22 a month by pooling them inside Containers with workerd; the thread covers why, the durability trade-off and when real Durable Objects are still cheaper. The figures are the author’s calculations, not a bill.
Robert Chandler
@bertie_ai · Original 𝕏 post
keeping 1,000 cloudflare durable objects awake costs $4,050/month i got the same 1,000 running for $22/month. same code, still on cloudflare 🧵
Thread post: each awake Durable Object is billed as 128 MB while each used about 200 KB in workerd; he packed them into containers, autoscaled 1 to 5 containers for 6,000 WebSockets and moved objects mid-write with 0 writes lost.
Read on 𝕏Robert Chandler
@bertie_ai · Original 𝕏 post
cloudflare bills every awake DO like it’s using 128mb of ram. in workerd (their open source runtime) each one used ~200kb so i packed them into containers instead autoscaled 1 to 5 containers for 6,000 websockets moved objects between containers mid-write, 0 writes lost https://t.co/HqvAfNDNgW
Thread post: he compares his approach with celld (self-hosted Durable Objects on S3), which he ran in the same containers; roughly tied on CPU, with celld’s durability better than his.
Read on 𝕏Robert Chandler
@bertie_ai · Original 𝕏 post
@rough__sea shipped celld in august: self-hosted durable objects on s3 i went the other way. stay on cloudflare, stop paying per object ran celld in the same containers. roughly tied on cpu, and his durability story is way better than mine https://t.co/ZtWtBtlT6O
Thread post: a real Durable Object only acknowledges a write after replication; in his pool a container crash loses up to 30 seconds of writes, so keep real Durable Objects for anything with money in it.
Read on 𝕏Robert Chandler
@bertie_ai · Original 𝕏 post
the catch: a real DO doesn’t ack a write until it’s replicated. that guarantee is the magic here, if a container crashes you lose up to 30s of writes for cursors, presence, game state, agent scratchpads that’s fine. for anything with money in it, keep real DOs
Thread post: if objects mostly sleep, real Durable Objects are cheaper; pooling wins once they are awake 2+ hours a month. Containers may boot in distant locations (from California he got Paris and Osaka). Links the code.
Read on 𝕏Robert Chandler
@bertie_ai · Original 𝕏 post
also if your DOs mostly sleep, real ones are cheaper anyway. pooling wins once they’re awake 2+ hrs a month and containers boot wherever. from california i got paris and osaka lol code: https://t.co/9ONaBuGq78
Undated
The thread’s repository README: it describes the pool as roughly 180× cheaper for always-awake objects in the author’s comparison, advises keeping mostly hibernating objects as real Durable Objects, and writes checkpoints as one R2 segment per node every 30 seconds (2 PUTs per flush) to avoid per-object PUT costs.
Open original sourceThread post: the official containers library relays every WebSocket frame through JavaScript, caps out around 1,000 messages per second and bills each one; a one-line passthrough fixed it. The whole testing bill was $0.63.
Read on 𝕏Robert Chandler
@bertie_ai · Original 𝕏 post
had claude code build this in a day. best find: the official containers library relays every websocket frame through javascript, caps out around 1k msgs/sec and bills each one. a one line passthrough fixed it whole cloudflare bill for all the testing was $0.63
Thread post: links a live demo of the pool.
Read on 𝕏Robert Chandler
@bertie_ai · Original 𝕏 post
you can mess around with it here: https://t.co/hYS1KLYeCZ
Author’s reply to a suggestion to pack many objects into one Durable Object instead: he thinks that loses the actor model, lets one object get overloaded with no way to move state, and would quickly hit the limit of 6 concurrent subrequests.
Read on 𝕏Robert Chandler
@bertie_ai · Original 𝕏 post
@banskyrich tell me more… i think you’d then lose the beauty of the actor model and any one DO could quite easily get overloaded without an ability to move the state from one DO to another. plus the 6 concurrent sub request limit would likely bite pretty fast
More to read
cloudflare-cost-guard
Louis Cai’s open-source rules and TypeScript base class for keeping Durable Object alarms and Worker schedulers from runaway loops.
mcwangcn reports $1,300 in D1 charges after a bot attack.
@mcwangcn says D1 writes previously cost over a thousand dollars and separately mentions Workers CPU charges without giving an amount. He later shares a Cloudflare bill and says $1,300 of its $3,600 came from D1 after a bot attack.
sylwair: nearly $900 of usage in under two days after a project mistake.
@sylwair says a recent project mistake ran up nearly $900 in less than two days. He says he spotted it in Cloudflare's billable-usage view and stopped the abnormal service, and in a reply adds that the daily billing figures appeared with a delay, so the amount did not visibly drop after he stopped it.