Cloudflare Developer Platform · Generally available

A tiny stateful server for every thing in your app.

A Durable Object is a small server that exists exactly once, globally — one per chat room, document, game, user, or AI agent. Compute, storage, and WebSockets live together in one place, so you can build real-time, multiplayer apps without a degree in distributed systems.

  • Free tier included
  • Zero servers to manage
  • Millions of objects, one API
object = env.ROOMS.getByName("design-review")
clients the one object broadcast same name → same object, from anywhere
Built on Cloudflare's network — 330+ cities Powers Cloudflare Queues, Workflows & Agents Trusted by teams like Liveblocks for production real-time
The problem

Real-time apps break the stateless model.

Say you're building a group chat. Your stateless functions scale beautifully — by having no memory. So every message becomes a round trip to a distant database, every broadcast needs a pub/sub layer, and every "who's typing?" needs a cache. Three users in the same room might hit three different servers in three different regions.

  • Two writes race on the same row — someone's message wins, someone's vanishes
  • WebSockets need sticky sessions, Redis pub/sub, and lifecycle glue
  • State lives an ocean away from the users acting on it
  • You end up operating Redis, Postgres, a queue, and a socket fleet — for a chat room

The fix isn't more infrastructure. It's a different shape: put the state where the logic runs — once, globally.

The mental model

Three ideas, from simple to precise

You don't need the whole architecture on day one. Start with a picture, add the code, then meet the machinery underneath. Each level is true — each one just adds resolution.

1 The picture

One tiny server per thing you care about

Imagine you could snap your fingers and get a small, private server for each chat room, each document, each game match, each user. It holds that one thing's state in memory and on disk, handles its messages, and talks to its clients directly.

That's a Durable Object. You never provision it — saying its name is enough to summon it. There is only ever one of it in the world, so everyone who names the same thing reaches the same place.

Hold onto this: "a tiny stateful server that exists once, globally, per thing you care about." Everything else is detail.
room:"design-review" everyone in this room lands here doc:"q3-launch-plan" every edit flows through here match:"lobby-7f3a" the authoritative game state user:"jamie@corp.com" their agent, limits & sessions its own compute its own storage its own compute its own storage its own compute its own storage its own compute its own storage one object each, worldwide
2 The code

It's just a class — the name is the address

You write a JavaScript/TypeScript class. Cloudflare turns every named instance of it into one of those tiny servers, created on first use. No deploy per object, no connection strings — the platform routes any request, from any of 330+ cities, to the one live instance for that name.

Methods on the class are plain RPC calls from your Worker. State you write in one request is simply there for the next — no cache invalidation, no session affinity.

Two lines to remember: env.ROOMS.getByName("design-review") summons the object; calling stub.addMessage(...) runs code inside it.
chatroom.tsts
import { DurableObject } from "cloudflare:workers";

// One instance of this class exists per room name — globally.
export class ChatRoom extends DurableObject {
  async addMessage(user: string, text: string) {
    this.ctx.storage.sql.exec(
      "INSERT INTO messages (user, text, ts) VALUES (?, ?, ?)",
      user, text, Date.now(),
    );
    this.broadcast({ user, text });   // push to every WebSocket
    return this.messageCount();
  }
}

// In your Worker: name → the one object, anywhere on Earth.
const room = env.ROOMS.getByName("design-review");
await room.addMessage("nadia", "shipping friday 🚀");
3 The machinery

The six mechanics that make it safe

Durable Objects feel simple because six deliberate design decisions do the distributed-systems work for you. Expand any card for the precise version.

Globally unique

Each name maps to exactly one live instance in the whole world. Cloudflare routes every request — from any city — to it.

The precise version

IDs come from getByName(), newUniqueId(), or idFromString(). The platform guarantees at most one instance per ID is active, so "the object" is a single point of coordination you can reason about like a local program.

Single-threaded execution

One event loop per object, like a browser tab. Requests to the same object are handled one at a time — state updates can't race.

The precise version

Execution is cooperatively multitasked, and input/output gates hold new events while storage writes are in flight — so get/put sequences behave atomically without you taking locks. Need more throughput? Make more objects, not threads.

Storage lives with compute

Every object owns a private, transactional SQLite database on the same machine it runs on. Reading state isn't a network call.

The precise version

Up to 10 GB per object via ctx.storage.sql (plus a key-value API), synchronous because it's local. Writes are durable and strongly consistent, with point-in-time recovery over the last 30 days. It's the same SQLite lineage that powers D1.

WebSocket hibernation

An object can hold thousands of live WebSockets, then go to sleep between messages. Connections stay open; the billing meter stops.

The precise version

ctx.acceptWebSocket(ws) hands sockets to the runtime. When the room goes quiet, the object is evicted from memory while sockets stay connected; the next message re-creates it and invokes webSocketMessage(). Idle rooms cost ~nothing.

Alarms — it can wake itself

An object can schedule its own future execution: tick a game loop, retry a delivery, expire a hold, run a nightly rollup — per entity.

The precise version

ctx.storage.setAlarm(when) persists a wake-up; the runtime calls your alarm() handler at that time with guaranteed at-least-once execution and retries with backoff. It's a per-object cron and queue-runner, built in.

On-demand lifecycle

Objects are created on first access, evicted when idle, and revived when named again — with state intact. Make millions; pay for use.

The precise version

There's no capacity planning and no hard limit on object count. Each object starts near the first request that names it (location hints can steer this), runs while needed, and costs nothing while evicted — storage persists across generations.

Interactive

Watch one object coordinate the world

A live simulation of a shared counter — the "hello world" of coordination. Send increments from six cities and watch them route to one Durable Object, queue up, and apply in order. Then flip to the traditional architecture and watch the same traffic race a faraway database.

Nothing has happened yet.
Press Send +1 to fire a single request, or Auto-play to let the world type away on its own.

Counter value 0
Requests handled 0
Lost updates 0
Event log durable object
  1. Events will appear here in the order the system sees them…
Durable Object mode: every request — even two arriving in the same millisecond — is applied one at a time by the object's single thread. The count can't be wrong, and every client gets the broadcast. Timings are illustrative, not to scale.
Architecture, honestly

The same app, two shapes

Neither architecture is "wrong" — they're built for different problems. Here's what actually changes when the state moves in with the compute.

Stateless workers + external state

Conventional
clients LB worker ×N worker ×N worker ×N Redis locks pub/sub database queue
  • Consistency is your job: locks, transactions, retries, idempotency keys
  • Real-time push means a socket fleet with sticky sessions + pub/sub fan-out
  • Every state touch is a cross-region network hop
  • Great fit for stateless request/response & heavy analytical queries

Workers + Durable Objects

One primitive
clients Worker at the edge doc:"roadmap" logic · sql · sockets · alarms room:"support" logic · sql · sockets · alarms match:"7f3a" logic · sql · sockets · alarms
  • Consistency by construction: one single-threaded owner per entity
  • WebSockets, storage, and scheduling are built into the same object
  • State is local to the logic — reads and writes skip the network
  • Per-object throughput is finite (~1k req/s) — shard hot entities
Feature comparison between a stateless architecture with external state and Durable Objects
Concern Stateless + Redis/Postgres Durable Objects
Where state lives In separate services, in one or a few regions Inside the object, on the machine running its code
Consistency per entity Eventual by default; strong costs locks & transactions Strong & serialized — one single-threaded owner per entity
Real-time push Socket servers + sticky sessions + pub/sub Every object is a WebSocket server (with hibernation)
Scheduled work External cron / queue workers Built-in Alarms API, per object, with retries
Scaling unit Add servers / shards; rebalance state by hand Create more objects — millions, on demand, no planning
Idle cost Clusters run (and bill) 24/7 Idle objects hibernate; storage pennies per GB
Ops surface Redis + DB + queue + socket fleet + glue One primitive, deployed with wrangler deploy
Watch out for Race conditions, cache invalidation, fan-out lag Hot single objects (~1k req/s soft limit) — shard by design
Use cases, with receipts

Where “one object per thing” wins

Every card below follows the same honest pattern: what strains in a stateless-plus-Redis build, and what the Durable Object version actually looks like — in code.

Collaborative docs & whiteboards

The Figma / Google Docs shape: many cursors, one source of truth, updates in milliseconds. One Durable Object per document.

Where stateless + Redis strains

Two editors on different worker instances submit edit #47 at once. Order has to be decided somewhere — so you build an OT/CRDT relay server, keep it warm, give it sticky sessions, and sync through Redis pub/sub across instances.

That relay is now a stateful service you shard, fail over, and babysit — the exact thing serverless promised to remove.

The Durable Object version

The document is the server. Every editor's WebSocket lands on the same object, which applies edits in arrival order — a total order, for free, from single-threaded execution.

Snapshots and history live in the object's own SQLite. Ten thousand documents? Ten thousand objects, created on first open, hibernating when everyone leaves.

document.tsts
export class Document extends DurableObject {
  async fetch(request: Request) {
    const { 0: client, 1: server } = new WebSocketPair();
    this.ctx.acceptWebSocket(server);        // hibernation-friendly
    return new Response(null, { status: 101, webSocket: client });
  }

  async webSocketMessage(ws: WebSocket, raw: string) {
    const edit = JSON.parse(raw);
    // Single-threaded = edits apply in one global order. No OT server.
    this.ctx.storage.sql.exec(
      "INSERT INTO ops (site, op, ts) VALUES (?, ?, ?)",
      edit.site, JSON.stringify(edit.op), Date.now());
    for (const peer of this.ctx.getWebSockets())
      if (peer !== ws) peer.send(raw);       // fan out to every cursor
  }
}

WebSockets in Durable Objects Liveblocks runs production collaboration on this pattern.

Developer experience

The whole API fits in your head

A Durable Object is a class with superpowers: RPC methods, WebSocket handlers, a local SQL database, and an alarm clock. Here's a complete tour — every snippet is the real, current API.

From zero to deployed: scaffold a Durable Object project, run it locally with a real simulated runtime, then ship to 330+ cities. There is no step three — no VPC, no cluster, no capacity review.
counter.tsts
import { DurableObject } from "cloudflare:workers";

// A tiny stateful server. One per name, worldwide.
export class Counter extends DurableObject {
  async get() {
    return (await this.ctx.storage.get<number>("value")) ?? 0;
  }
  async increment(amount = 1) {
    const value = (await this.get()) + amount;
    await this.ctx.storage.put("value", value);   // durable write
    return value;
  }
}

// The Worker in front: plain HTTP in, RPC to the object.
export default {
  async fetch(request: Request, env: Env) {
    const name = new URL(request.url).searchParams.get("name");
    if (!name) return new Response("missing ?name", { status: 400 });

    const counter = env.COUNTERS.getByName(name);  // summon by name
    const value = await counter.increment();       // typed RPC call
    return new Response(`${name} = ${value}`);
  },
};
$ npm create cloudflare@latest my-app -- --template=cloudflare/templates/hello-world-do-template
$ npx wrangler dev # full local simulation, storage included
$ npx wrangler deploy
✨ Deployed to 330+ cities in ~10 seconds
Pricing

Start free. Pay for what actually runs.

Durable Objects are included in every Workers plan — there's a real free tier, and hibernation means idle objects stop the meter. Numbers below are the current published rates.

Workers Free

$0 / month

Real quota, real SQLite storage — enough to ship a working product.

  • 100,000 requests per day
  • 13,000 GB-s of compute duration per day
  • 5 million SQL rows read / day · 100,000 written / day
  • 5 GB of SQLite storage included
  • WebSockets, alarms & SQLite-backed objects included
Start for free
Most popular

Workers Paid

$5 / month, then usage

Generous included usage; overage only past these each month:

  • 1M requests included, then $0.15 / million
  • 400,000 GB-s included, then $12.50 / million GB-s
  • 25B SQL rows read included, then $0.001 / million
  • 50M SQL rows written included, then $1.00 / million
  • 5 GB-month storage included, then $0.20 / GB-month
Upgrade in the dashboard
Hibernation stops the meter Duration bills only while an object is active in memory. A room with open WebSockets but no messages hibernates — thousands of quiet rooms round to zero.
WebSocket messages bill 20:1 Incoming WebSocket messages count as 1/20th of a request — 100 chat messages ≈ 5 billable requests. Real-time stays affordable at volume.
Storage is boring, on purpose $0.20 per GB-month after the included 5 GB, across all objects. No per-database fees — a million tiny tenant DBs cost the same as one big one.

Rates shown are Cloudflare's published Durable Objects pricing as of August 2026; duration is metered against 128 MB per active object. Objects on the legacy key-value storage backend have separate unit rates. See the pricing docs for the authoritative table.

Battle-tested

Cloudflare builds Cloudflare on it

Durable Objects aren't a side product — they're the coordination layer under Cloudflare's own platform, and under real-time products you may already use.

Cloudflare released Durable Objects at just the right time for us. Without Cloudflare, hosting WebSocket servers might have required at least four additional people just for management. Using Durable Objects, we can provide serverless capabilities without a dedicated team.
Liveblocks Real-time collaboration infrastructure, built on Durable Objects
330+cities in Cloudflare's network — objects start near their users
10 GBof SQLite per object, transactional and point-in-time recoverable
objects per account — no hard limit, no capacity planning
20%of the web runs on the same network your objects do
FAQ

The questions everyone asks

Is a Durable Object a database?

It's compute and storage in one unit. Each object carries a private SQLite database (up to 10 GB), so the right picture is "millions of small databases, each with a brain," not one big shared one. If you want a single conventional SQL database, that's D1 — which is built on the same SQLite-in-DO technology.

What happens when nobody is using an object?

It's evicted from memory and stops billing duration. Its storage persists durably. The next request that names it brings it back — same state, usually in milliseconds. With WebSocket hibernation, even objects with thousands of open connections can sleep between messages.

Where does my object physically run?

By default, near the first request that creates it, in one of the Cloudflare data centers that run Durable Objects. It stays put so its state stays local; every request worldwide routes to it. You can steer placement with location hints, and jurisdiction options (like the EU) can pin data for compliance.

Single-threaded? Won't that be slow?

Single-threaded is per object — it's what makes state changes race-free. Throughput comes from having many objects: each handles roughly 1,000 requests/second, and you can have millions of them working in parallel. If one entity gets hotter than that, shard it across several objects and merge — the same trick databases use, minus the database.

How do I call one from my code?

Through a Worker binding: env.ROOMS.getByName("my-room") returns a stub, and calling its methods is a typed RPC into the object. Browsers and other clients reach objects through your Worker over plain HTTPS or WebSockets — so any stack that can speak HTTP can use them, even if the rest of your app isn't on Cloudflare.

Durable Objects vs. KV, D1, and R2 — when do I use which?

Rule of thumb: KV for read-heavy, eventually-consistent config and cache; D1 for one relational database queried from anywhere; R2 for large files; Durable Objects whenever multiple clients or requests must agree on changing state — rooms, sessions, locks, queues, agents. DOs are the only one of the four that also runs your code.

Is this production-ready?

Durable Objects are generally available and run on Cloudflare's production network. Cloudflare's own Queues, Workflows, and Agents SDK are built on them, and companies like Liveblocks run their real-time infrastructure on them. SQLite-backed storage is the default for new classes and includes 30-day point-in-time recovery.

What are the honest limits I should know?

Per object: ~1,000 req/s soft limit, 10 GB SQLite storage, 30s CPU per request (configurable up to 5 minutes), 32 MiB max incoming WebSocket message. Per account: no hard limit on object count. Design guideline: many small objects beat one big one — that's the whole idea. Full details in the limits docs.

Your first object is five minutes away.

Scaffold a project, run it locally, and deploy a tiny stateful server to 330+ cities — on the free tier, no credit card required.

npm create cloudflare@latest — then pick the Durable Objects template.

View more demos Get $10 off Kimi K3