Stateful Compute Finally Reaches the Edge

Workers Durable Objects Beta:
A New Approach to Stateful Serverless

When Workers launched in 2017, the promise was simple: code running at the network edge could be faster, easier to deploy, and cheaper to operate than traditional server-based apps. Edge storage arrived with Workers KV, but that only offered eventually-consistent data. Strong consistency and real-time coordination between clients still required hosting some part of your stack elsewhere.

That gap closes today with the start of a closed beta for Durable Objects. The new primitive gives developers a serverless way to manage state with transactional consistency and to coordinate live traffic between multiple clients — all without ever routing through a centralized origin server. Requests for a beta invite are now open.

What Actually Makes an Object "Durable"

Durable Objects don't map neatly onto any existing cloud service, which made naming them a project in itself. The final choice breaks down into three concepts:

  • Objects: These are objects in the object-oriented programming sense. You write a class in JavaScript or any language Workers supports, and its methods define the public interface. Each instance pairs that code with private state.
  • Unique: Every object has a globally unique ID and exists in exactly one location worldwide at any moment. Any worker that knows the ID can message the object, and those messages will always converge on the same instance.
  • Durable: Unlike ordinary JavaScript objects, these can persist state to disk. Because storage is private to each object, it stays co-located, so the object can maintain a consistent in-memory copy and operate with zero latency. Idle objects shut down and are recreated on demand.

Two Primary Capabilities

Durable Objects offer two distinct functions:

  • Storage: Attached durable storage is always physically co-located with its object, enabling strong, transactional consistency with very low latency. This breaks down monolithic databases into many small logical units that scale effortlessly, in keeping with the serverless philosophy.
  • Coordination: Until now, incoming requests to Workers were load-balanced randomly across instances, so there was no way to route two clients to the same worker for live coordination. Durable Objects fix this: requests on a common topic can be forwarded to a single object that acts as a go-between without touching storage. This enables real-time chat, collaborative editing, video conferencing, pub/sub queues, game sessions, and similar workloads.

Since most coordination workloads need WebSockets — and most WebSocket-heavy apps need coordination — the beta introduces WebSocket support for Workers alongside Durable Objects.

No Regions, Just Logical Grouping

With Durable Objects, Cloudflare decides which datacenter hosts each object and can migrate objects transparently as usage patterns shift. You no longer need to pre-plan geographic regions or keep data close to a predetermined audience. Instead, you mirror your application's natural data model: a document editor creates one object per document, a chat app one object per chat room. There's no practical ceiling on object count since each one carries minimal overhead.

The Use Case That Changes Everything: Live Co-Editor

Real-time collaborative editing is a famously hard problem. If Alice and Bob edit a shared spreadsheet, you want every keystroke to appear instantly on the other user's screen. Polling a database won't cut it — the latency is poor, and write conflicts will mount as users in different time zones fight over the same cells.

Every major collaborative editor solves this with a live coordination point. Both users open a WebSocket to one server, which relays keystrokes between them without involving storage. The coordinator holds the canonical in-memory state, resolves conflicts in the moment, and asynchronously persists the results. DIY coordination like this has historically sat out of reach for serverless developers who lacked any control over request routing.

Durable Objects close that gap. An object can serve as the assigned coordinator, and Cloudflare will place it near the active users, migrating if needed for optimal latency. Writes that need durability can be saved locally with strong consistency right away, or the entire document can live on the edge and skip a traditional database altogether.

Counter Example: Consistency Without Disk Reads

Here's a minimal counter object that supports increments, decrements, and reads over HTTP. It stays consistent even under concurrent requests because every operation lands on a single object instance. Reads are served in memory, with no disk access required.

export class Counter {
  // Constructor called by the system when the object is needed to
  // handle requests.
  constructor(controller, env) {
    // `controller.storage` is an interface to access the object's
    // on-disk durable storage.
    this.storage = controller.storage
  }

  // Private helper method called from fetch(), below.
  async initialize() {
    let stored = await this.storage.get("value");
    this.value = stored || 0;
  }

  // Handle HTTP requests from clients.
  //
  // The system calls this method when an HTTP request is sent to
  // the object. Note that these requests strictly come from other
  // parts of your Worker, not from the public internet.
  async fetch(request) {
    // Make sure we're fully initialized from storage.
    if (!this.initializePromise) {
      this.initializePromise = this.initialize();
    }
    await this.initializePromise;

    // Apply requested action.
    let url = new URL(request.url);
    switch (url.pathname) {
      case "/increment":
        ++this.value;
        await this.storage.put("value", this.value);
        break;
      case "/decrement":
        --this.value;
        await this.storage.put("value", this.value);
        break;
      case "/":
        // Just serve the current value. No storage calls needed!
        break;
      default:
        return new Response("Not found", {status: 404});
    }

    // Return current value.
    return new Response(this.value);
  }
}

Once the class is bound to a Durable Object namespace, any worker worldwide can reach a particular Counter instance with a few lines of code:

// Derive the ID for the counter object named "my-counter".
// This name is associated with exactly one instance in the
// whole world.
let id = COUNTER_NAMESPACE.idFromName("my-counter");

// Send a request to it.
let response = await COUNTER_NAMESPACE.get(id).fetch(request);

Reference Demo: Edge-Hosted Chat

A fully open source chat demo shows the pattern end-to-end, running entirely on the edge with an object tied to each chat room. Users connect via WebSockets, and messages relay peer-to-peer through the object rather than writing to storage on every send. Durable storage only keeps history around for later retrieval.

The demo also puts Durable Objects to a second job: rate limiting by IP. Each IP maps to an object that tracks request frequency and can temporarily block abusive senders even across different rooms. These rate-limit objects use no durable state at all, stashing nothing — they're pure coordination with a simple resets-meant-sometimes.

The whole app is a few hundred lines of code with a minimal config, scaling to any number of rooms limited only by Cloudflare's capacity. An individual room caps out at the speed of a single-threaded object, which is still far beyond human-scale throughput.

Other Pain Points That Fit the Pattern

  • Shopping carts: A storefront can stay static while a per-user object glues the cart near the customer.
  • Game servers: A single object tracks match state, hosted close to the players.
  • IoT coordination: Devices inside a home coordinate via a nearby object instead of faraway infrastructure.
  • Social feeds: One object per user aggregates multiple subscriptions.
  • Comment or chat widgets: Each article gets its own object to run live widgets while origin serves static content only.

Where Durable Objects Are Headed

Durable Objects today are a lower-level building block rather than a full database. They offer no cross-object queries or multi-object transactions without additional application logic. But every large distributed database is internally built from shards responsible for one slice of data — Durable Objects are a natural home for those shards.

The projected next step is edge-resident databases where each logical chunk is itself a Durable Object, functioning fully distributed with no home region. Any team can build such a database on top of this primitive. Right now, though, Durable Objects stand on their own as the first piece of the edge storage puzzle.

Rollout and Beta Access

Durable Objects is entering beta gradually over the next several months. Cloudflare is taking a measured approach because of the responsibility involved in providing durable storage. Some features described here are not yet fully enabled; the documentation details current beta limitations.

Developers interested in early access can request an invite and describe their use case. Cloudflare will prioritize the most compelling applications for the initial rollout.

WebSocket Support

Durable Objects enable Workers to act as full WebSocket endpoints — both as client and server. Previously, Workers could only proxy WebSocket traffic to a backend. This direct protocol support is particularly powerful when paired with Durable Objects. When a client connects via WebSocket, the connection can be forwarded to a specific Object. Since messages can then be addressed by the Object's unique ID, the Object can relay server-generated events down the WebSocket to the client. The chat demo uses WebSockets this way, and its source code illustrates the pattern.

Comparing Durable Objects with Workers KV

Workers KV, introduced two years ago, is a global key-value store with a specific design profile: eventually consistent with "last write wins" semantics. This suits low-latency reads of rarely changing data well, but makes KV unsuitable for frequently updated state or changes that must be visible worldwide immediately. Concurrent writes from multiple regions can easily overwrite each other.

Durable Objects sit at the other end of the storage spectrum. They are not primarily a storage product — many use cases don't use durable storage at all. When they do provide storage, the emphasis is on transactional guarantees and immediate consistency. The trade-off is fundamental: transactions require coordination at a single location, so clients far from that point experience latency proportional to the speed of light. Cloudflare plans to mitigate this by auto-migrating Objects closer to where they are actively used.

In short: Workers KV remains the right choice for serving static content, configuration, and similar data globally, while Durable Objects target dynamic state and coordination. Cloudflare also plans to rebuild Workers KV internally on top of Durable Objects for better performance.

Why Not CRDTs?

Conflict-free Replicated Data Types (CRDTs) and Operational Transforms (OTs) permit simultaneous edits across locations without synchronization or data loss. These power real-time collaborative editing, behaving like an automated, deterministic git merge that always converges to the same state. However, CRDTs are a demanding technology to apply correctly. Only certain data structures lend themselves to conflict resolution without risking data loss, and arbitrary merge resolution is inherently hard — automated algorithms won't always get it right, especially when merges arrive in arbitrary order.

Cloudflare's position: for most applications, CRDTs are overly complex and constrain the data structures you can represent. A single authoritative coordination point per document, which is exactly what Durable Objects provide, is usually far simpler.

That said, Durable Objects don't preclude CRDT usage. If an Object's state is CRDT-friendly, an application can replicate it into multiple Objects across regions and synchronize them via CRDT. This can be an optimization worth implementing when an app demonstrates it's needed.

Serverless State, Redefined

Traditional serverless compute has been consciously stateless. Each event — typically an HTTP request — executes in isolation. This model works because events are the natural logical unit we use when designing applications; we think in terms of events, not servers or containers. Offloading that infrastructure burden to the cloud provider has been serverless's great success.

State, however, has always been an exception. Developers needing persistence had to attach a traditional database or a coordination service, reintroducing the operational headaches serverless was meant to eliminate. The burden includes not only scaling for load, but sharding into regions for global traffic — arguably the more cumbersome problem.

The serverless philosophy applied to state means granular, application-aligned shards of state. The logical unit is not a table, collection, or graph — it depends on the application itself. For chat, that unit is a room; for a collaborative spreadsheet, it's the document; for an online store, the cart. When the physical storage unit matches these logical units, the provider can handle scalability and regionality. That is precisely what Durable Objects deliver.