Skip to content
Back to Cloud Services

Cloudflare Durable Objects Stateful Coordination

Single-instance stateful objects with strong consistency, ideal for realtime rooms, counters, and coordination.

CloudflareAdvanced

Why

Durable Objects give you a strongly-consistent single instance per ID — the only way to do realtime rooms, rate limiters, and distributed locks on Workers. Storage is transactional SQLite, no external DB needed.

Cloudflare's network spans 330+ cities in 125+ countries, serving 20% of all internet traffic. Workers have 0ms cold starts (isolate-based) and the free tier covers 100k requests/day.

When

Use DO for WebSocket rooms, per-user rate limiting, distributed locks, and any 'exactly one' coordination. Avoid for high-fanout (use Queues) or simple CRUD (use D1).

How

1. Define class — export class Room implements DurableObject { async fetch(request) {...} } 2. Bind — [[durable_objects.bindings]] name="ROOM" class_name="Room" 3. Migrate — [[durable_objects.migrations]] new_sqlite_classes=["Room"] 4. Get instance — const id = env.ROOM.idFromName("room-42"); const stub = env.ROOM.get(id) 5. State — this.ctx.storage.put("count", 1); const c = await this.ctx.storage.get("count") 6. WebSocket — server accept, store in this.ctx.getWebSockets(), broadcast on message 7. Alarm — this.ctx.storage.setAlarm(Date.now() + 60000) for scheduled wake

Example

export class ChatRoom implements DurableObject { async fetch(request: Request): Promise<Response> { const pair = new WebSocketPair(); const [client, server] = Object.values(pair); this.ctx.acceptWebSocket(server); return new Response(null, { status: 101, webSocket: client }); } async webSocketMessage(ws: WebSocket, msg: string) { const count = (await this.ctx.storage.get<number>("count") || 0) + 1; await this.ctx.storage.put("count", count); for (const peer of this.ctx.getWebSockets()) peer.send(`count=${count}`); } } // Worker routes to DO by room name (single instance per room) export default { async fetch(request: Request, env: Env) { const id = env.ROOM.idFromName("general"); return env.ROOM.get(id).fetch(request); }, };

Common Problems

  • ⚠Single-instance bottleneck — one DO handles all requests for its ID, hot IDs throttle
  • ⚠Migration class renames break — old IDs orphaned, use migrations with old_class_names
  • ⚠WebSocket memory limits — 1MB per message, large broadcasts need chunking

Best Practices

  • ✓Use Hibernatable WebSockets — ctx.acceptWebSocket, frees memory between messages, cheaper
  • ✓Shard hot keys — room-42-shard0..N distributes load across DOs
  • ✓Use alarms not setInterval — DOs can hibernate, alarms wake them reliably

FAQ

What is Cloudflare Durable Objects Stateful Coordination and what problem does it solve?

Single-instance stateful objects with strong consistency, ideal for realtime rooms, counters, and coordination. It lets developers deploy, store, and scale without self-managing infrastructure — a core reference for cloud service selection.

How do I get started with Cloudflare Durable Objects Stateful Coordination in 5 minutes?

Two steps to run it: (1) Define class — export class Room implements DurableObject { async fetch(request) {...} }; (2) Bind — [[durable_objects.bindings]] name="ROOM" class_name="Room". Validate on the free tier first, then wire into production.

What is the #1 pitfall with Cloudflare Durable Objects Stateful Coordination?

The most frequent issue is: Single-instance bottleneck — one DO handles all requests for its ID, hot IDs throttle. Run a pre-launch checklist item by item, and add policy/config scanning in CI.

What are the best practices for Cloudflare Durable Objects Stateful Coordination?

Best practices for Cloudflare Durable Objects Stateful Coordination include: Use Hibernatable WebSockets — ctx.acceptWebSocket, frees memory between messages, cheaper; Shard hot keys — room-42-shard0..N distributes load across DOs; Use alarms not setInterval — DOs can hibernate, alarms wake them reliably. The first one — "Use Hibernatable WebSockets — ctx.acceptWebSocket, frees memory between messages, cheaper" — should be a team default baked into your IaC templates.

How do I control cost and avoid bill surprises with Cloudflare Durable Objects Stateful Coordination?

Three ways to prevent overspend: (1) tag every resource with env/team and enable billing alarms; (2) set budget thresholds to trigger Slack/email alerts; (3) review idle resources in Cost Explorer regularly and clean them up. Most Cloudflare Durable Objects Stateful Coordination options offer a free tier — validate within free quota before scaling.