nyacg / do-on-container
git clone https://github.com/nyacg/do-on-container.git
A repository for do-on-container
β
stars, 24h
+50
stars, 7 days Β· #897
+50
stars, 30 days Β· #5,903
50
β
total Β· +50% this week
5
forks Β· 1 open issues
Star history starts 2026-10-20; the chart appears after the second daily snapshot.
LanguageTypeScript
Licenseβ
Created2026-10-14 (6d ago)
Last push1d ago
Watchers0
OwnerUser
Links
- GitHub: github.com/nyacg/do-on-container
- Releases Β· Issues Β· Hacker News mentions
README excerpt
# do-pool: Durable Objects, bin-packed into Cloudflare Containers Run your Durable Object classes either as **real Durable Objects** or **hundreds-per-container inside workerd** (Cloudflare's open-source runtime) on Cloudflare Containers. The same class runs on both sides, behind the same Worker, with the same bindings. For objects that are awake most of the time but doing little (game loops, presence, agents waiting on LLMs, upstream feeds), the pool is **~180Γ cheaper**: 1,000 always-awake objects cost about $22 a month instead of $4,050. Objects that mostly hibernate should stay real DOs. See `POST.md` for the write-up and `bench/results` for the raw data. Live demo (while it's up): https://do-pool.do-pool-lab.workers.dev. It has two demos (live cursors and a Yjs editor), each with a backend switch, plus a pool dashboard. > **v2** (`docs/v2.md`) adds: > > - alarms that survive moves and crashes > - native `ctx.container` with region-local nodes > - snapshot sleep/wake > - Dynamic Workers + facets, with hot code swaps > - a sandboxed process per tenant app for untrusted code > - bindings from pooled objects: KV, R2, Workers AI, other Workers and other DOs, with the same code > (docs/bindings.md; example: AI chat rooms) > > An API parity suite runs the same assertions against real DOs, pooled DOs, real facets and pooled > facets. Preview: https://do-pool-v2.do-pool-lab.workers.dev. Try the dynamic-app > examples in the playground. | Capability | Real DO | do-pool v1 | do-pool v2 | |---|---|---|---| | SQL / KV / transactions / WebSocket hibernation API | β | β | β | | Alarms (incl. retries) | β | β οΈ lost on move or crash | β | | Zero lost writes on planned moves | n/a | β οΈ rare race | β | | Write acknowledged after replication | β | β RPO 30 s | β RPO 30 s on hard failure | | Near its users | β | β | β region-local nodes | | Scale to zero | β | β οΈ | β snapshot sleep/wake | | Dynamic code (Worker Loader + facets), hot swaps | β | β | β | | Untrusted tenant code | β | β | β process + namespaces per app, in a microVM | | Point-in-time recovery | β | β | β | ## How it works [code] - **`Placement`** (`src/placement.ts`) is the "load balancer DO". It assigns objects to nodes (sticky, least-loaded), scales nodes up and down from pushed CPU and connection stats, rebalances hot nodes by live-migrating batches of objects, and fences moves with per-assignment epochs. - **`PoolNode`** (`src/pool-node.ts`) is one per container. It extends `@cloudflare/containers` but hands WebSockets to the runtime with `getTcpPort().fetch()` instead of the library's JavaScript proxy (see *Gotchas*). - **`PortableDurableObject`** (`objects/portable.ts`) is the base class for pooled objects. It's a no-op on Cloudflare. In the pool it tracks writes, snapshots storage, hydrates from the last checkpoint on a fresh disk, and closes sockets with 1012 when the object moves. - **Checkpoints** (`objects/ckpt-store.ts`): every 30s each node writes **one R2 segment** containin