WDurable Objects, explained
01 / 18

Run Durable Objects with celld.

How does a Durable Object operate, which problems fit it, and what changes when the model runs on infrastructure you choose?

Durable Objects
the runtime model
celld
the new implementation
start with the mechanism →

Working implementation: writing.krasnoperov.me

WThe object boundary
02 / 18

One entity’s behavior is usually spread across infrastructure.

A Durable Object makes that entity the runtime and consistency boundary.

Request handlersreceive events and apply rules
Database rowsretain durable facts
Locks and queuescoordinate concurrent and background work
Schedulerswake durable work later
Durable ObjectOne logical thing owns its address, decisions, local storage, and time.
WWhat it is
03 / 18

One globally unique instance of a class, reached by ID, running in one place, with private durable storage.

IdentityThe logical object survives processes and machines.
LocationAt one moment, one active place coordinates it.
ExecutionEvents enter one single-threaded instance.
StorageOnly that object accesses its attached database.

Cloudflare Durable Objects glossary

WA callable reference
04 / 18

Start with the business key—not a database lookup.

Choose an example. The key deterministically addresses the authority for that thing.

piece:7
namespace
idFromName()
returns a stub
WritingCoach
piece 7
A stub is a remote reference bound to the object ID. Creating it starts nothing; calling it routes or wakes the current instance.
WThe process is temporary
05 / 18

A Durable Object does not run forever.

Its in-memory instance may disappear. Its logical identity and stored state do not.

1Event arrivesA request, RPC call, WebSocket message, or alarm targets the ID.
2ActivateThe runtime creates the class instance and attaches storage.
3ServeMemory is a useful cache while the instance stays resident.
4HibernateIdle compute can be evicted. No permanent server is required.
5ReconstructA fresh instance resumes from the same ID and durable state.

Durable Object lifecycle

WSingle-threaded, precisely
06 / 18

One piece of JavaScript runs at a time. But another request may enter while the first waits.

Network wait: interleaving is possible. Storage operation: another request waits.

network waitanother request may enter
request A
await fetch
request B enters
B changes state
A resumes
A re-checks
durable storageinput and output gates
request A
storage operation · B waits
write unfinished
durable
response leaves

Input and output gate definitions

WStorage belongs to the object
07 / 18
// inside one Durable Object
const row = ctx.storage.sql.exec(
  "SELECT revision FROM documents
   WHERE name = ?", "draft"
).one();

ctx.storage.transactionSync(() => {
  saveRevision();
  queueJob();
});

Each object gets a private embedded database.

Strong local consistency

Storage methods are atomic and isolated. Synchronous SQL work can share a transaction.

Real local queries

Tables, indexes, JSON, and FTS can live next to the object’s decisions.

Intentional boundary

There is no arbitrary SQL join across all objects. Keep a separate index or shared relational store when the product needs one.

SQLite-backed Durable Object storage

WThe object has a clock
08 / 18

Who wakes the object after the request and process are gone?

The object stores one future wake-up time. That is enough to drive a durable schedule in SQLite.

insert scheduled rows
setAlarm(earliest)
object may disappear
alarm()
process due rows
re-arm

At least once

The runtime retries a failed alarm. Therefore the handler must tolerate duplicate execution.

Durable Object alarms

WThe fit test
09 / 18

Can you name the thing that must decide consistently?

Select an atom of coordination.

Different keys scale across different objects. Contention remains with the logical thing that causes it.
WChoose the boundary
10 / 18

And which entities do not fit?

Durable Objects are strongest when correctness belongs to one addressed entity—not many unrelated keys.

Need
Durable Object
Relational database
Workflow engine
One keyed authority
Excellent: address and execute at the coordination key.
Possible with transactions and locks.
Usually not the main abstraction.
Broad relational query
Build a projection or external index.
Excellent: joins, constraints, reports.
Workflow visibility, not ad hoc analysis.
Long multi-service workflow
Possible, but cross-object steps are sagas.
Stores facts; orchestration is application code.
Excellent: durable history and activities.
Per-entity timer
Excellent: alarm belongs to the entity.
Needs scheduler and worker machinery.
Excellent when part of a larger workflow.
WCase study · persistent agent
11 / 18

A writing coach that supports the writer without replacing them.

The piece has identity, memory, background work that outlives a request, and reasons to wake later.

WRITERChoose a topicSet the direction and questions worth exploring.
COACHCollect materialFind useful facts, angles, and questions—not a draft.
WRITERWrite the textThe writer owns the argument and prose.
COACHCommentAnalyze what was actually written and suggest the next revision.
The model call is temporary. The piece around it must persist.
WChoosing the object boundary
12 / 18

One writing piece becomes one WritingCoach object.

Different texts have independent state, jobs, retries, and alarms. They should not block each other.

The piece list is a separate choice

This demo uses a WritingLibrary object. A relational table would work too; piece-local correctness does not depend on it.

User 42several writing pieces
Piece indexWritingLibrary DO or relational table
WritingCoach · piece Acollecting material independently
WritingCoach · piece Bwaiting for feedback
WritingCoach · piece Csleeping until its alarm
WAgent work survives the request
13 / 18

The model call is disposable. The job protocol is durable.

Every asynchronous step is represented as state the object can recover.

VERSIONPin draftsave the exact input the coach must analyze
STORAGEInsert pending jobdurable intent, attempts, and due time
ALARMReturn acceptedthe browser is no longer required
CLAIMUntil a deadlinethis temporary claim is the lease
OPENAICall modeloutbound work owns no continuity
JOB IDStore resultthe same job cannot append twice
WAt least once, made explicit
14 / 18

Crash after the answer. Before the commit.

The lease expires. The alarm retries. The model may answer again.

One owner ≠ exactly once

Ownership prevents concurrent authorities. It cannot make an external API call and a local commit one transaction.

job_abc is retried

The new instance restores state and reclaims the expired job.

appliedJobs.includes("job_abc")

The append receipt turns duplicate delivery into the already-committed result.

The design lesson

Put an idempotency key at every external-effect seam.

WBoundary test · identity
15 / 18

A stable identity can address several independent authorities.

GitHub OAuth authenticates at the edge. The immutable numeric ID becomes routing.

GitHub OAuthUser 4581825

Temporary token is used for one profile lookup, then discarded.

github:4581825WritingLibrary

Piece discovery and limits.

github:4581825WritingAccount

Subscription, allowance, reservations, and audit.

login renamedSame objects

Profile data changes. Durable identity and admin authority do not move.

WMoney-like state and a saga
16 / 18

One account balance is local. Charging work crosses objects.

Select the sequence to see where the transaction boundary ends.

Polar signs a webhook. The edge verifies the exact raw message before routing it to the account ID.
WThe same model, self-hosted
17 / 18

celld makes the stateful core an infrastructure choice.

Nodes are replaceable. The bucket is fleet authority and durable replica store.

Not the whole Cloudflare platform

celld runs the compatible Worker and Durable Object core. Managed ingress, global placement, KV, Cache API, and other services remain outside that boundary.

node A
receives request
node B · owner
active piece SQLite
node C
replaceable compute
S3-compatible bucketatomic ownership record
SQLite replicas
node leases
deployments
1 · two nodes try; one atomic write wins
2 · this is compare and swap
3 · replicate SQLite continuously
4 · restore on a new owner

denoland/celld · Apache-2.0 · alpha runtime

WThe reusable design question
18 / 18

Name the long-lived thing. Give it an address, decisions, local data, and time.

Durable Objects provide a different default for entity-local coordination. celld makes that model deployable on infrastructure you choose.