Web Analytics Made Easy - Statcounter
BaseKV
Sign InSign Up
Back to Articles

Cloudflare Durable Objects vs a Key-Value Store: When You Need Each (2026)

Workers KV, Durable Objects, and D1 each solve a different state problem on Cloudflare. A clear, accurate map of consistency, latency, write limits, and portability - plus where a portable disk-backed KV store fits.

BaseKV Team11 min read
durable-objectscloudflare-workers-kvd1key-value-storeedge-computingstrong-consistency

In 2026 Cloudflare made a confident bet: it told developers to put SQLite inside every Durable Object, marketed as "zero-latency SQLite in every Durable Object," and quietly turned a niche coordination primitive into a general-purpose stateful building block. At the same time Workers KV stayed where it has always been - a globally replicated, read-optimized cache - and D1 grew up into a managed SQLite database you reach over the network. The result is that a developer standing inside a Cloudflare Worker now has at least three native ways to keep state, plus the option of an external store, and the names do not make the differences obvious.

This article maps those four options against the questions that actually decide the choice: how consistent is a read after a write, how fast is a point lookup, how often can you write to one key, and how locked-in are you to one vendor. We will be accurate to Cloudflare's real model rather than to the marketing, and then we will be honest about the lane where a portable, disk-backed key-value store like BaseKV beats all three of the native primitives. There is no single winner here. There is only a workload, and the storage layer whose tradeoffs fit it.

Workers KV: read-optimized and eventually consistent

Workers KV is the oldest of the three and the easiest to misuse. It is a globally distributed key-value store optimized for one thing: serving the same value to enormous read volume from locations close to the user. A read hits a nearby cache, and after the first read in a region the value is typically warm and served in single-digit milliseconds. That is the whole point of KV, and it is genuinely excellent at it.

The catch is consistency. Workers KV is eventually consistent. A write does not immediately appear everywhere; Cloudflare's own documentation states that changes are usually visible globally within about 60 seconds, and a read in another region can return the previous value during that window. There is also a practical write ceiling: you should not write to a single key faster than roughly once per second, because KV is not built to be a high-frequency mutation log. It is built to be written rarely and read constantly.

That makes KV ideal for configuration, feature flags, routing tables, edge content, and read-heavy session lookup where a stale read for a few seconds is harmless. It is the wrong tool for a counter, a rate limiter, a lock, or anything where two requests racing on the same key must agree on the result. If you have hit that wall, the failure mode and the way out are covered in Cloudflare Workers KV limits in 2026.

Durable Objects: strong consistency, one object at a time

A Durable Object is a different animal. Each object is a single, named, addressable instance of a class, and Cloudflare guarantees there is exactly one live copy of a given object in the world at a time. Requests to that object are processed by one single-threaded execution context, so writes to its state are serialized. With the SQLite storage backend, each object gets its own embedded SQLite database co-located with the code that uses it, which is what the "zero-latency SQLite" framing refers to: the storage is in the same place as the compute, so there is no network round trip to a separate database for the object's own data.

This buys you strong consistency and serializability for free, scoped to one object. A read after a write inside the same object always sees the write. Two concurrent requests to the same object cannot interleave in a way that corrupts state, because they do not actually run concurrently. That is exactly the property you want for a chat room, a multiplayer game session, a per-user inbox, a rate limiter keyed to one account, or any coordination problem that has a natural single owner.

The tradeoffs are equally real. A Durable Object lives in one location - the region near wherever it was first used - so a client on the other side of the planet pays a network round trip to reach it. Throughput on a single object is bounded by its single thread, so a global hot object is a bottleneck, not a feature. And the model only shines when your state partitions cleanly into independent objects. If your access pattern is "read any of a million keys from anywhere, very fast," you are fighting the design. Cloudflare's own storage options guide is candid that DO is for coordination and per-entity state, not for global low-latency reads.

D1: managed SQLite over the network

D1 is Cloudflare's managed SQLite database. Unlike the SQLite inside a Durable Object, D1 is a standalone database you query over the network from your Worker, with a primary location and read replicas. It gives you real relational SQL - joins, indexes, transactions, a schema - which neither KV nor a bare DO key-value API offers ergonomically.

D1 is the right call when your data is genuinely relational and your queries are genuinely SQL: a dashboard backend, a small app's primary store, anything with foreign keys and ad-hoc reporting. It is strongly consistent against its primary. The costs are that you are talking to a database over a network hop rather than co-located storage, write throughput is bounded by the single primary, and like the other two it is a Cloudflare-only primitive. D1 competes less with KV and more with "do I need a real database" - and if the answer is yes and you are on Cloudflare, it is a reasonable default.

The honest comparison

Here is the same four options laid against the dimensions that decide the choice. Read it as "what is this thing actually good at," not "which is best," because best depends entirely on the workload.

| Dimension | Workers KV | Durable Objects | D1 | External KV (BaseKV) | | --- | --- | --- | --- | --- | | Consistency | Eventually consistent (~60s global) | Strong, serializable per object | Strong against primary | Strong on a single node, read-after-write | | Read latency | Excellent for hot keys, edge-local | Low within the object's region, RTT from afar | Network hop to primary or replica | Predictable point reads, depends on placement | | Write limits | ~1 write/sec per key, write-rarely | Bounded by one thread per object | Bounded by single primary | Predictable point writes, single-writer per store | | Portability | Cloudflare only | Cloudflare only | Cloudflare only | Runs anywhere, Redis wire protocol | | Best for | Config, flags, edge content, read-heavy sessions | Per-user/per-room coordination, locks, counters | Relational app data, SQL queries | Durable cross-environment KV, no vendor lock-in |

A few notes so the table is not read as a scoreboard. KV's "weakness" on consistency is the direct price of its strength on global read latency; that is the eventual-consistency bargain, not a bug. A Durable Object's single thread is what makes its strong consistency cheap; it is a feature for coordination and a ceiling for fan-out reads. And the external-KV row is not claiming to beat DO at coordination or KV at edge fan-out - it is a different lane, which the next section is about.

Where a standalone KV store fits

Everything above assumes you are all-in on Cloudflare. The moment you are not, the calculus changes. The three native primitives are excellent and tightly coupled to one platform: you cannot run Workers KV, a Durable Object, or D1 on your laptop, in a customer's VPC, in a CI job, or on a box at another cloud. For a lot of teams that coupling is fine. For others it is the whole problem.

A standalone disk-backed key-value store like BaseKV occupies the lane the Cloudflare primitives cannot reach. It speaks the Redis wire protocol, so your existing clients and code work unchanged, and it persists everything to a single B+tree file on disk for real durability rather than a replicated cache. It runs the same way in every environment - dev, CI, staging, production, on whatever cloud or metal you like - which means one store and one mental model across all of them instead of "KV in prod, something else locally." The performance story is predictable point reads and writes rather than the eventual-consistency-for-edge-fan-out bargain, which is what you want when the data is durable application state you read and write directly. If you have outgrown a managed edge cache and want ownership, the case is laid out in the Cloudflare Workers KV alternative and in persistent key-value storage.

The point is not that an external KV store is "better" than Durable Objects. It is that it answers a different question. DO answers "how do I coordinate one entity's state with strong consistency at the edge." An external KV answers "how do I keep durable key-value state I fully own, identically, everywhere." Those rarely compete for the same workload, and when a team thinks they do, it is usually because they reached for an edge primitive to solve a portability problem it was never meant to solve.

A decision framework

Strip away the names and the choice comes down to four clear cases.

  • Pick Workers KV when the data is read far more than it is written, a stale read for up to a minute is acceptable, and you want edge-local read latency at high volume. Config, feature flags, routing tables, published content, and read-heavy session lookups are the textbook fits. See serverless key-value database for the broader serverless framing.
  • Pick Durable Objects when state partitions naturally into independent entities that each need strong consistency and serialized writes - a room, a user, a document, a lock, a counter. You accept that each object lives in one region and is throughput-bounded by its single thread, because the coordination guarantee is the point.
  • Pick D1 when the data is relational and the queries are SQL: joins, indexes, transactions, ad-hoc reporting. It is the "I actually need a database" answer for a Cloudflare-native app.
  • Pick an external KV store when you want a durable, portable key-value store you own and can run identically across every environment, with predictable point-read and point-write performance and no lock-in to one cloud's primitives. This is also the right call when one store has to serve dev, CI, and multiple clouds, or when you simply do not want your state language to be a single vendor's API. The general use cases live in edge caching with a KV store and in key-value store vs Redis in 2026.

Most real architectures end up mixing these rather than choosing one. KV for the config a Worker reads on every request, a Durable Object for the per-room coordination, and an external durable KV for the application state you want to keep and move freely. The mistake is treating them as interchangeable because they all "store key-value data." They do not store it the same way, and the way is the decision.

Common questions

Can I use Durable Objects as a general key-value store?

You can, but you usually should not for a global read-heavy workload. A DO gives you strong consistency for one object's state, and its storage is co-located with that object in one region. If you try to use a single DO as a shared global KV, every reader on the planet routes to that object's region and contends on its single thread. For "read any key from anywhere, fast" you want Workers KV or an external KV store; for "coordinate one entity's state" you want the DO.

Is the SQLite in a Durable Object the same as D1?

No. The SQLite backend inside a Durable Object is an embedded database private to that one object, co-located with its compute - that is the "zero-latency" claim, since there is no network hop to the object's own data. D1 is a standalone managed SQLite database you query over the network and can share across many Workers and objects. Cloudflare's SQLite-in-Durable-Objects post describes the embedded model in detail. Use the DO's SQLite for one entity's serialized state; use D1 for shared relational data.

Why pick an external KV store over Cloudflare's native primitives?

Portability and ownership. Workers KV, Durable Objects, and D1 are excellent within Cloudflare but cannot run anywhere else, so your state language is tied to one platform. A standalone disk-backed KV store speaks the Redis protocol, persists to disk for real durability, and runs identically in development, CI, and any cloud. If you are not fully committed to Cloudflare, or you want a single store across many environments, that portability is worth more than any one native primitive's edge-specific advantage.


Related: Cloudflare Workers KV Alternative, Cloudflare Workers KV Limits in 2026, Edge Caching with a KV Store, Persistent Key-Value Storage, Key-Value Store vs Redis in 2026.