know.2nth.aiTechnologytechcloudflareDurable Objects
Technology · Cloudflare · Skill Node

Durable
Objects.

Single-writer stateful compute at the edge. Each Durable Object is a uniquely addressable instance with in-memory state, durable storage, and WebSocket support. The primitive behind real-time collaboration, game servers, and anything that needs strong consistency per entity.

TechnologyStateful ComputeOpen TierLast updated · Apr 2026

A named object with state that survives requests.

Durable Objects solve the problem Workers can't: state that persists across requests and coordinates concurrent access. Each DO has a unique ID, a single location where it runs, and a transactional key-value storage API. Because there's exactly one instance per ID at any time, you never have to worry about race conditions — all requests to that ID are serialised.

The "durable" part: the object's storage survives restarts. The "object" part: it's a JavaScript class with methods you call over RPC or HTTP. Think of it as a micro-service with exactly one instance, pinned to a location, with built-in persistence.

The killer feature is WebSocket hibernation. A DO can accept thousands of WebSocket connections, and when there are no messages, it hibernates — you only pay for active time, not idle connections.

Class, storage, and WebSocket hibernation.

01

Defining a Durable Object

A DO is a class with a fetch() method. You access its transactional storage via this.ctx.storage. The binding in wrangler.toml lets Workers create and address DO instances.

# wrangler.toml
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"

[[migrations]]
tag = "v1"
new_classes = ["Counter"]

// Counter Durable Object
export class Counter {
  constructor(ctx, env) {
    this.ctx = ctx;
  }

  async fetch(req) {
    let val = (await this.ctx.storage.get("count")) || 0;
    val++;
    await this.ctx.storage.put("count", val);
    return new Response(val.toString());
  }
}
02

Addressing from a Worker

Workers address DOs by name or unique ID. The idFromName() method maps a string to a deterministic ID — so "room:lobby" always routes to the same instance.

export default {
  async fetch(req, env) {
    const id = env.COUNTER.idFromName("global-counter");
    const stub = env.COUNTER.get(id);
    return stub.fetch(req);
  }
};
03

WebSocket hibernation

DOs can accept WebSocket connections and hibernate when idle. The webSocketMessage and webSocketClose handlers wake the object only when there's activity.

export class ChatRoom {
  async fetch(req) {
    const [client, server] = Object.values(new WebSocketPair());
    this.ctx.acceptWebSocket(server);
    return new Response(null, { status: 101, webSocket: client });
  }

  async webSocketMessage(ws, msg) {
    // Broadcast to all connected clients
    for (const conn of this.ctx.getWebSockets()) {
      conn.send(msg);
    }
  }
}

Where it bites you.

Location

Each DO lives in one location

A DO instance runs in a single data centre (usually near where it was first accessed). Requests from distant users cross the network to reach it. This is a feature for consistency, but a cost for latency.

Throughput

Single-threaded per instance

All requests to one DO instance are serialised. If you need parallelism, shard across multiple DOs (e.g., one per user, one per room).

Storage cost

$0.20/GB-month for storage

DO storage is more expensive than R2 or KV. Use it for hot, frequently-accessed state. Archive cold data elsewhere.

Migrations

Class renames require migration tags

Renaming or deleting a DO class requires a migration in wrangler.toml. Forgetting this causes deploy failures.

When it fits. When it doesn't.

✓ Use it when
  • You need strong consistency per entity. Counters, rate limiters, shopping carts, collaborative documents — anything where concurrent access needs coordination.
  • Real-time WebSocket applications. Chat rooms, multiplayer game state, live cursors. Hibernation makes idle connections effectively free.
  • You need a coordination point between Workers. Leader election, distributed locks, or single-writer patterns.

Where this node connects.

Go deeper.