πŸ“ˆ GH Trending Explorer 🎲 Surprise me

← all repos

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

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