Quick answer: Durable Objects are not a faster Redis. For pure caching, Redis is faster, has richer data structures, and has a vastly larger ecosystem. What Durable Objects give you that Redis cannot is a single authoritative instance per key, globally, with your code running in the same place as the state. That is what makes exact cross-region rate limiting, WebSocket rooms, and collaborative state possible without ever writing a distributed lock.
The most common one-line description of Durable Objects is Redis with compute attached. It is close enough to be understood and wrong enough to be dangerous, because it invites you to use Durable Objects for the jobs Redis already does better, and then be disappointed.
The real difference is structural. Redis is a data structure server: it holds data, and your logic lives somewhere else. A Durable Object is compute and storage fused into a single instance, of which exactly one exists in the world per ID, and which is single-threaded.
This article covers why that structural difference matters, which problems it genuinely changes, and where Redis remains the better tool. Every number here comes from Cloudflare official documentation, checked as of July 2026.
Redis and Durable Objects are not the same category of thing
Redis stores data. You send a command, it returns a value. Your code runs on a different machine from the state. When you need a read-modify-write that is more complex than a single command, you write a Lua script or reach for a distributed lock โ both of which mean you are now maintaining correctness machinery yourself.
A Durable Object puts the code next to the state, and Cloudflare guarantees that every request addressed to a given ID routes to the same instance โ regardless of which of Cloudflare data centers it entered from, and regardless of continent. That instance is single-threaded. Which means the entire class of race conditions that force you to write locks in Redis simply does not exist by construction.
What Redis cannot do
Rate limiting that must be exact across regions
Say you sell an API priced per request, and your contract promises the customer 10,000 calls per minute. Traffic arrives simultaneously from Thailand, Singapore, and Germany.
If you place a Redis replica in each region so that reads are fast, you no longer have a single authoritative counter. Replication is asynchronous, so two regions can both approve a request that should have been the one over the line. The customer who paid for 10,000 gets 12,000.
You can fix that by using one Redis primary for the whole world. Correctness comes back โ but now you own a single point that you must operate, design failover for, and pay a cross-ocean round trip to on every request. When it goes down, every rate limiter in the system goes down. In other words: you have rebuilt what Durable Objects already are, and you now have to run it.
With Durable Objects, you use the customer ID as the object key. Every request from that customer lands on the same instance, anywhere in the world. That instance is single-threaded, so incrementing the counter is atomic by construction. No lock. No Lua script. No race.
Coordination and collaborative state
Documents several people edit at once. A game room with shared state. A kanban board where everyone sees the card move in real time. These need two things: one place where state authoritatively lives, and a place where the merge logic runs, right next to it.
Redis gives you the first and not the second. Your merge logic runs on some application server that has to fetch state from Redis, compute, write back, and then fan out to everyone. Meanwhile another request is doing the same thing on a different server. That is exactly where locks enter your life.
In Durable Objects, the room is an object. The merge logic runs inside the object. The state lives inside the object. Every participant holds a WebSocket to that same object. There is no cross-network state fetch, no pub/sub fan-out across servers, and no lock.
WebSockets that can sleep
Redis does not hold your user connections. You need real servers keeping WebSockets open, and those servers burn RAM the entire time a connection exists, whether or not a single message ever arrives.
Durable Objects have the WebSocket Hibernation API, which stops duration charges while the object is idle and eligible for hibernation. Cloudflare documentation is explicit: an idle Durable Object that qualifies for hibernation does not incur duration charges, even during the brief window before the runtime actually hibernates it. The billing consequence of this is large, and it is spelled out below.
Architectural comparison
| Dimension | Durable Objects | Redis |
|---|---|---|
| What it is | Compute + storage fused into one instance per key | Data structure server; your code lives elsewhere |
| Consistency per key | One authoritative instance, globally, single-threaded | Strong on a single primary; eventual across replicas |
| Read-modify-write | Atomic by construction, no lock needed | Needs Lua, MULTI/EXEC, or a distributed lock |
| Holds WebSockets | Yes, with a Hibernation API | No โ you need separate servers for that |
| Cache-hit speed in one region | Slower โ the request must reach the instance, which may be a continent away | Faster โ in-memory, same network |
| Data structures | SQLite or key-value per object | Strings, hashes, lists, sets, sorted sets, streams, HyperLogLog |
| Throughput per key | Soft limit of roughly 1,000 requests/sec per object | Substantially higher on a single key |
| Ecosystem and hiring | New; Cloudflare-specific | Enormous; client libraries everywhere; engineers already know it |
| Operations | None โ fully managed | You run it, or you buy a managed service |
Limits and pricing, as of July 2026
Two numbers deserve your attention. First, the soft limit of roughly 1,000 requests per second per individual object. Second, duration is billed in wall-clock time while the object is active or idle but unable to hibernate โ and it is billed for the full 128 MB of memory allocated to the object, regardless of how much you actually use.
| Metric | Workers Free | Workers Paid |
|---|---|---|
| Requests | 100,000 / day | 1 million / month, then $0.15 per million |
| Duration | 13,000 GB-s / day | 400,000 GB-s / month, then $12.50 per million GB-s |
| SQL rows read | 5 million / day | 25 billion / month, then $0.001 per million rows |
| SQL rows written | 100,000 / day | 50 million / month, then $1.00 per million rows |
| SQL stored data | 5 GB total | 5 GB-month, then $0.20 per GB-month |
| Storage per object | 5 GB total across the account | 10 GB per object (account total unlimited) |
Two billing details matter in practice. Incoming WebSocket messages are billed at a 20:1 ratio โ 100 incoming messages count as 5 requests โ and outgoing messages are free. And an active outbound connection keeps a Durable Object in memory and incurs duration charges for up to 15 minutes per connection, even with no incoming requests.
A worked example: a chat app with 10,000 concurrent WebSockets
Say you build chat for a games company: 100 rooms, 100 people in each, so 10,000 WebSockets held open at once. Each person sends a message every now and then โ call it one per minute.
The structure
One room is one Durable Object. Everyone in a room connects a WebSocket to that same object. When a message arrives, the object broadcasts it to every socket in the room. No cross-server pub/sub. No sticky sessions to configure, because a request carrying a given room ID always arrives at the same object anyway.
The one thing you must get right is using the WebSocket Hibernation API rather than a plain accept(). Cloudflare documentation states plainly that calling accept() on a WebSocket incurs duration charges for the entire time the WebSocket is connected.
The actual numbers, from Cloudflare own documentation
Cloudflare works exactly this case in its pricing examples. For 100 Durable Objects each holding 100 hibernatable WebSockets, with each client sending one message per minute and each message taking 10 ms to process, running 24 hours a day for a month, the estimated total is about $10.00 per month โ $3.09 in requests, $1.91 in compute duration, plus the $5 minimum monthly usage.
Compare that to a different Cloudflare example: 100 Durable Objects each holding 50 WebSockets โ only 5,000 connections, and only 8 hours a day โ but without hibernation. Estimated total: about $138.65 per month, of which $133.24 is compute duration.
Read those two side by side. The second case has half the connections and runs a third of the time, and costs roughly fourteen times more. Hibernation removes duration charges for the time the object is simply sitting there holding sockets. That single API choice is the difference between the two bills.
The rate limiter, in the same system
If you also need a strict per-user message limit, you create a second Durable Object keyed by user ID. Before broadcasting, the Worker asks that object whether the user is within quota. Because the object is the single point of truth for that user, the count is exact โ it does not matter which continent the message came from, or whether two messages arrived in the same millisecond.
You do pay for that: the request has to reach the object, which may be far away. That is the price of exactness โ and it is exactly the same price you would pay with a single global Redis primary, except you do not have to operate the Redis.
When Redis wins
This section matters most, because people who have just discovered Durable Objects tend to reach for them everywhere, and that is a mistake.
Pure caching
If what you need is a fast cache next to your servers, Redis wins outright. It is an in-memory store in the same VPC as your application. A Durable Object is an instance that may be half a world away from the request. Using a Durable Object as a cache means trading latency for a consistency guarantee you did not need.
Data structures and ecosystem
Redis gives you sorted sets that build a leaderboard in one command, streams for event logs, HyperLogLog for approximate unique counts, pub/sub, pipelining, fifteen years of client libraries, redis-cli, and engineers who already know how to debug it. In Durable Objects, you write all of that yourself. That is a real cost, even if it does not appear on an invoice.
Throughput on a single key
Cloudflare documents a soft limit of roughly 1,000 requests per second per individual Durable Object. If your key is a hot spot โ one global counter every request touches โ you will hit that ceiling and the object will start returning overloaded errors. Redis handles far more traffic against a single key.
Your team already runs Redis
If you have a Redis that works, monitoring that is wired up, runbooks that exist, and no actual consistency bug hurting you, migrating to Durable Objects is a waste of time. Bring Durable Objects in for the specific cases Redis cannot solve, and let Redis keep doing what it is good at.
Summary
The right question is not Durable Objects or Redis. It is: does this job require a single authoritative point of decision? If yes, use Durable Objects. If no โ and what you actually need is a fast cache โ Redis is the better tool. Most real systems use both.
If you are still working out whether Workers fit your system at all, we have written about when not to use Cloudflare Workers, and about how the runtimes compare in Cloudflare Workers vs AWS Lambda.
Cipher designs and implements systems on the Cloudflare Developer Platform for businesses in Thailand. If you have real-time or coordination work that Redis is struggling with, we can assess the architecture and tell you which parts are worth moving โ and which should stay exactly where they are.
Frequently Asked Questions
Are Durable Objects faster than Redis
Generally no. For a cache hit against a Redis server in the same region, Redis is faster, because the request does not have to travel to an instance that may be on another continent. You choose Durable Objects when you need single-point consistency, not when you need raw speed.
How many requests per second can one Durable Object handle
Cloudflare documents a soft limit of roughly 1,000 requests per second per individual object, while the number of objects per namespace is unlimited. Your design therefore has to avoid hot keys where every request lands on the same object, or that object will start returning overloaded errors.
What is WebSocket Hibernation and why does it matter
Hibernation lets a Durable Object holding open WebSockets stop incurring duration charges while it has no work to do. In Cloudflare own pricing example, 100 objects each holding 100 hibernatable WebSockets cost roughly $10.00 per month, whereas calling accept() on a WebSocket normally incurs duration charges for the entire time the WebSocket is connected.
Can Durable Objects do exact rate limiting across regions
Yes. Every request addressed to a given ID routes to the same instance globally, and that instance is single-threaded, so incrementing a counter is atomic by construction. You do not need a distributed lock or a Lua script. The cost is latency, because the request may have to travel to an object that is far away.
How are Durable Objects billed
As of July 2026, the Workers Paid plan includes 1 million requests per month and then charges $0.15 per million, plus 400,000 GB-s of duration per month and then $12.50 per million GB-s. Duration is billed against the full 128 MB of memory allocated to the object, regardless of how much you actually use.

