vd
GitHubLinkedInTwitterRésumé
← Back to all posts

I Thought I Needed a Database. Then I Needed Cloudflare's Durable Objects

7 min read

There is a particular kind of engineering problem I really enjoy.

The kind where you start with:

“This should be easy.”

And three hours later you’re reading documentation for a technology you didn’t even know existed that morning.

Recently caught myself exploring and working on a system that needed persistent, real-time interactions between a client and an AI agent.

At first, my brain went where it usually goes:

We need a database.

Obviously.

We need to keep track of the resource.

Its state.

Changes happening to it.

Maybe some metadata.

Easy.

Database.

Done.

Except… not quite.

The problem wasn't really storing the data

This is where I think the distinction gets interesting.

A database is very good at answering questions like:

“What is the current state of this resource?”

or:

“What changes have happened to it?”

But the problem was slightly different.

We needed something that could own a piece of state while it was actively being worked on.

Something that could receive events.

Coordinate changes.

Maintain state.

Handle real-time connections.

And importantly, be responsible for that particular piece of state.

We weren’t just asking:

“Where do we put this data?”

We were asking:

“What owns this state while it is changing?”

That is a different question.

Enter the Durable Object

This was one of those moments where a technology suddenly makes more sense because you have a problem for it.

Cloudflare’s Durable Objects are essentially stateful serverless objects: each object has a globally unique identity, its own durable storage, and a single-threaded execution model. Cloudflare also supports WebSockets inside Durable Objects, making them particularly useful for applications that need a persistent real-time coordination point.

And I remember thinking:

Oh.

This isn’t just a database.

It’s more like:

a little server with an identity and a memory.

That mental model clicked for me.

A normal Worker is great at handling a request:

Request
   ↓
Worker
   ↓
Response

But a Durable Object lets you say:

Workspace #123
       ↓
Durable Object
       ├── state
       ├── storage
       ├── logic
       └── WebSocket connection

Now the conversation itself can have an identity.

And that’s exactly the kind of abstraction we were looking for.

The “never stop” part

There was another reason this was interesting.

Some applications don’t just need to receive a request, perform some computation, and return a response.

They need to coordinate ongoing changes.

Imagine a shared workspace.

One user changes something.

Another user sees the change.

An event arrives.

The state gets updated.

Another event arrives.

The system needs to make sure those changes are handled consistently.

Suddenly the architecture starts looking less like:

Request
  ↓
Compute
  ↓
Response
  ↓
Goodbye.

and more like:

User
   ↕
Shared Resource
   ↕
State
   ↕
Events

That’s where a stateful coordination point becomes interesting.

The Durable Object can represent that resource and act as the place where its state and incoming events are coordinated.

Cloudflare specifically documents WebSockets as a use case for Durable Objects because a Durable Object can act as a single point of coordination for long-lived connections and multiple clients.

The interesting part isn’t simply that a connection stays open.

It’s that the connection has somewhere stateful and consistent to belong to.

But does this mean Durable Objects replace databases?

No.

And this is probably the most important thing I learned.

A Durable Object is not “a better database.”

That isn’t really the comparison.

A database is fundamentally concerned with persisting and querying data.

A Durable Object is concerned with owning and coordinating stateful computation.

And, conveniently, Durable Objects also have durable storage attached to them. Cloudflare describes that storage as transactional and strongly consistent, and current Durable Objects can use either a key-value API or SQLite-backed storage.

So instead of thinking:

Database vs Durable Object

I now think:

Database
    ↓
Where is my data?
Durable Object
    ↓
Who owns this state
and coordinates what happens to it?

Sometimes the answer is:

Both.

And sometimes you don’t need the external database for that particular piece of the system at all.

The funny thing about building

This is probably my favourite part of the whole story.

I didn’t sit down one morning and decide:

“Today, I shall learn Cloudflare Durable Objects.”

Absolutely not.

I were trying to build something.

I hit a problem.

I searched.

I read.

I experimented.

And suddenly we’re reading about stateful serverless architectures and the actor model at 2am.

That’s one of the things I love about building software.

Projects force you to learn things tutorials never would.

You can read about WebSockets for days.

But when you actually need a persistent connection between a user and an AI agent, the concept suddenly becomes very different.

You can read about distributed state.

But when two parts of your application need to agree on what is happening inside one conversation, consistency stops being a theoretical word.

You can read about serverless.

But when you need something to behave like a long-lived entity without managing a server yourself, suddenly the abstraction matters.

Building gives concepts somewhere to land.

And then I found the funny contradiction

There is something almost contradictory about Durable Objects.

They’re durable, but they aren’t necessarily running forever.

A Durable Object can start when it’s needed, process requests, remain active while work is happening, and eventually hibernate when idle. Its durable state remains available across that lifecycle.

Which means the mental model isn’t:

“Keep my server alive forever.”

It’s closer to:

“Keep the identity and state alive. Run the computation when necessary.”

That’s a subtle difference.

And I think it is an increasingly useful way to think about modern applications.

Especially now that we’re building software where an “application” isn’t always a request-response function.

Sometimes it is a conversation.

Sometimes it is an agent.

Sometimes it is a room.

Sometimes it is a workflow.

Sometimes it is a user session that might last five seconds or five hours.

The thing that matters isn’t necessarily keeping a process alive.

It’s keeping the state of the thing alive.

I thought I needed a database

Looking back, I don’t think the initial thought was wrong.

I absolutely needed persistence.

I just hadn’t identified the actual problem yet.

I thought:

“Where do I store the conversation?”

The better question was:

“What represents this thing while it is changing?”

That shift in perspective led us to Durable Objects.

And that’s probably the bigger lesson I took from the experience.

Good architecture doesn’t always come from knowing more technologies.

Sometimes it comes from describing the problem more accurately.

Because once you describe the problem correctly, the technology has a much easier time introducing itself.

Apparently, mine introduced itself as a Durable Object.

References