Spencer AlgerBlog

Durable Objects, maaaan

I'm kinda obsessed with Durable Objects, a computing primitive available from Cloudflare, maybe invented there? The core idea is based on workers, which are really just JavaScript code that can respond to events like HTTP requests or CRON jobs, but they're just some JS code that can run in any datacenter anywhere around the world. They are hyper generic and have zero system-level dependencies.

Instance-iation

A Durable Object is a special type of Worker that always runs in a specific place (though there's no real way to know where that will be, it's probably based on who creates that object first). This is the first part of the magic. When you want to talk to a Durable Object you provide the SDK with a string key which uniquely identifies an instance of some class. The SDK will return a "stub" with async helpers on it that will proxy any method calls you make on the stub to the Durable Object, wherever it is in the world.

Those RPC calls transparently queue up somewhere while Cloudflare is busy figuring out where that key is allocated, globally, the Durable Object is woken up, and then the RPC is class instance is called using the same method name and arguments the worker somewhere else in the world used. Pretty simple RPC stuff so far, but the allocation of the instance is practically instantaneous and globally unique, which is really impressive.

Unique-ness

The next part of the magic is that Durable Objects have a little SQLite database attached to them that you can write to synchronously from the JS worker.

When you write to the database cloudflare automatically blocks your response from being sent back until your changes have been durably persisted, so you don't have to think about it, but if you don't write to the DB your response will send out instantly.

When your doThatThingYouDo() RPC method is called, you can synchronously check the state of your database, consume the return value, and write back to SQLite without having to worry about any other operation interacting with your database while you were holding onto that result, or calculating it, or whatever.

This is because the workers behind durable objects are single-threaded, though they have non-blocking I/O like a normal single Node.JS process. If you don't do anything with an async/await or a callback, then nothing else has a chance to execute and fuck with your state, making it super easy to reason about complex coordination in distributed, cloud-based, applications.

Concurrency

The solve for concurrency is equally simple, you can have an infinite number of different durable objects in the system, all working independently in their own globally distributed single-threaded worker instances with their own durable SQLite databases. When you need to have global state that all users of your system have access to, it goes in your big shared database, but there are a lot of interesting problems you can solve really elegantly by composing little swarms of these Durable Objects together, especially in this agentic world.