Products · Developer platform
Durable Objects
A special kind of Cloudflare Worker combining compute with storage
Pricing and limits
Pricing
As of Nov 3, 2026, from Cloudflare's docs, last updated there Oct 18, 2026. Licensed CC BY 4.0; navigation removed.
Durable Objects can incur two types of billing: compute and storage.
Note
Durable Objects are available both on Workers Free and Workers Paid plans.
- Workers Free plan: Only Durable Objects with SQLite storage backend are available.
- Workers Paid plan: Durable Objects with the SQLite storage backend are available. The key-value storage backend is only available to accounts that already have a key-value-backed namespace.
If you wish to downgrade from a Workers Paid plan to a Workers Free plan, you must first ensure that you have deleted all Durable Object namespaces with the key-value storage backend.
On Workers Free plan:
- If you exceed any one of the free tier limits, further operations of that type will fail with an error.
- Daily free limits reset at 00:00 UTC.
Compute billing
Durable Objects are billed for compute duration (wall-clock time) while the Durable Object is actively running or is idle in memory but unable to hibernate. Durable Objects that are idle and eligible for hibernation are not billed for duration, even before the runtime has hibernated them. Requests to a Durable Object keep it active or create the object if it was inactive.
For each metered dimension, billable usage is the amount consumed in excess of the included monthly allocation. This billable usage is rounded up to the next billable unit before the corresponding rate is applied. For example, 500,000 GB-s of billable compute duration is rounded up to 1,000,000 GB-s and billed accordingly.
| Free plan | Paid plan | |
|---|---|---|
| Requests | 100,000 / day | 1 million / month, + $0.15/million Includes HTTP requests, RPC sessions1, WebSocket messages2, and alarm invocations |
| Duration3 | 13,000 GB-s / day | 400,000 GB-s / month, + $12.50/million GB-s4,5 |
Footnotes
</summary>1 Each <a href="https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/">RPC session</a> is billed as one request to your Durable Object. Every <a href="https://developers.cloudflare.com/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/">RPC method call</a> on a <a href="https://developers.cloudflare.com/durable-objects/">Durable Objects stub</a> is its own RPC session and therefore a single billed request.
RPC method calls can return objects (stubs) extending <a href="https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/#lifetimes-memory-and-resource-management">RpcTarget</a> and invoke calls on those stubs. Subsequent calls on the returned stub are part of the same RPC session and are not billed as separate requests. For example:
let durableObjectStub = OBJECT_NAMESPACE.get(id); // retrieve Durable Object stub
using foo = await durableObjectStub.bar(); // billed as a request
await foo.baz(); // treated as part of the same RPC session created by calling bar(), not billed as a request
await durableObjectStub.cat(); // billed as a request
2 A request is needed to create a WebSocket connection. There is no charge for outgoing WebSocket messages, nor for incoming <a href="https://www.rfc-editor.org/rfc/rfc6455#section-5.5.2">WebSocket protocol pings ↗︎</a>. For compute requests billing-only, a 20:1 ratio is applied to incoming WebSocket messages to factor in smaller messages for real-time communication. For example, 100 WebSocket incoming messages would be charged as 5 requests for billing purposes. The 20:1 ratio does not affect Durable Object metrics and analytics, which reflect actual usage.
3 Application level auto-response messages handled by <a href="https://developers.cloudflare.com/durable-objects/best-practices/websockets/">state.setWebSocketAutoResponse()</a> will not incur additional wall-clock time, and so they will not be charged.
4 Duration is billed in wall-clock time as long as the Object is active and not eligible for hibernation, but is shared across all requests active on an Object at once. Calling accept() on a WebSocket in an Object will incur duration charges for the entire time the WebSocket is connected. It is recommended to use the WebSocket Hibernation API to avoid incurring duration charges once all event handlers finish running. For a complete explanation, refer to <a href="https://developers.cloudflare.com/durable-objects/platform/pricing/#when-does-a-durable-object-incur-duration-charges">When does a Durable Object incur duration charges?</a>.
5 Duration billing charges for the 128 MB of memory your Durable Object is allocated, regardless of actual usage. If your account creates many instances of a single Durable Object class, Durable Objects may run in the same isolate on the same physical machine and share the 128 MB of memory. These Durable Objects are still billed as if they are allocated a full 128 MB of memory.
</details>Storage billing
The Durable Objects Storage API is only accessible from within Durable Objects. Pricing depends on the storage backend of your Durable Objects.
- SQLite-backed Durable Objects (recommended): SQLite storage backend is recommended for all new Durable Object classes. Workers Free plan can only create and access SQLite-backed Durable Objects.
- Key-value backed Durable Objects: Key-value storage backend is only available on the Workers Paid plan.
SQLite storage backend
Storage billing on SQLite-backed Durable Objects
Storage billing for SQLite-backed Durable Objects will be enabled in January 2026, with a target date of January 7, 2026 (no earlier). Only SQLite storage usage on and after the billing target date will incur charges. For more information, refer to Billing for SQLite Storage.
| Workers Free plan | Workers Paid plan | |
|---|---|---|
| Rows reads 1,2 | 5 million / day | First 25 billion / month included + $0.001 / million rows |
| Rows written 1,2,3,4 | 100,000 / day | First 50 million / month included + $1.00 / million rows |
| SQL Stored data 5 | 5 GB (total) | 5 GB-month, + $0.20/ GB-month |
Footnotes
</summary>1 Rows read and rows written included limits and rates match <a href="https://developers.cloudflare.com/d1/platform/pricing/">D1 pricing</a>, Cloudflare's serverless SQL database.
2 Key-value methods like get(), put(), delete(), or list() store and query data in a hidden SQLite table and are billed as rows read and rows written.
3 Each setAlarm() is billed as a single row written.
4 Deletes are counted as rows written.
5 Durable Objects will be billed for stored data until the <a href="https://developers.cloudflare.com/durable-objects/best-practices/access-durable-objects-storage/#remove-a-durable-objects-storage">data is removed</a>. Once the data is removed, the object will be cleaned up automatically by the system.
</details>Key-value storage backend
| Workers Paid plan | |
|---|---|
| Read request units1,2 | 1 million, + $0.20/million |
| Write request units3 | 1 million, + $1.00/million |
| Delete requests4 | 1 million, + $1.00/million |
| Stored data5 | 1 GB, + $0.20/ GB-month |
Footnotes
</summary>1 A request unit is defined as 4 KB of data read or written. A request that writes or reads more than 4 KB will consume multiple units, for example, a 9 KB write will consume 3 write request units.
2 List operations are billed by read request units, based on the amount of data examined. For example, a list request that returns a combined 80 KB of keys and values will be billed 20 read request units. A list request that does not return anything is billed for 1 read request unit.
3 Each setAlarm is billed as a single write request unit.
4 Delete requests are unmetered. For example, deleting a 100 KB value will be charged one delete request.
5 Durable Objects will be billed for stored data until the data is removed. Once the data is removed, the object will be cleaned up automatically by the system.
Requests that hit the <a href="https://developers.cloudflare.com/durable-objects/reference/in-memory-state/">Durable Objects in-memory cache</a> or that use the <a href="https://developers.cloudflare.com/durable-objects/api/sqlite-storage-api/">multi-key versions of get()/put()/delete() methods</a> are billed the same as if they were a normal, individual request for each key.
Compute billing examples
These examples exclude the costs for the Workers calling the Durable Objects. When modelling the costs of a Durable Object, note that:
- Inactive objects receiving no requests do not incur any duration charges.
- The WebSocket Hibernation API can dramatically reduce duration-related charges for Durable Objects communicating with clients over the WebSocket protocol, especially if messages are only transmitted occasionally at sparse intervals.
- Pending I/O operations keep an object in memory for up to 15 minutes each. The object incurs duration charges during that time. For more information, refer to Lifecycle of a Durable Object.
Example 1
This example represents a simple Durable Object used as a co-ordination service invoked via HTTP.
- A single Durable Object was called by a Worker 1.5 million times
- It is active for 1,000,000 seconds in the month
In this scenario, the estimated monthly cost would be calculated as:
Requests:
- 1.5 million requests - included 1 million requests = 500,000 billable requests.
- (rounded) 1,000,000 requests x $0.15 / 1,000,000 = $0.15.
Compute Duration:
- 1,000,000 seconds * 128 MB / 1 GB = 128,000 GB-s.
- 128,000 GB-s is within the 400,000 GB-s included allocation = $0.00.
Estimated total: $0.15 (requests) + $0.00 (compute duration) + minimum $5/mo usage = $5.15 per month
Example 2
This example represents a moderately trafficked Durable Objects based application using WebSockets to broadcast game, chat or real-time user state across connected clients:
- 100 Durable Objects have 50 WebSocket connections established to each of them.
- Clients send approximately one message a minute for eight active hours a day, every day of the month.
In this scenario, the estimated monthly cost would be calculated as:
Requests:
- 50 WebSocket connections * 100 Durable Objects to establish the WebSockets = 5,000 connections created each day * 30 days = 150,000 WebSocket connection requests.
- 50 messages per minute * 100 Durable Objects * 60 minutes * 8 hours * 30 days = 72,000,000 WebSocket message requests.
- 150,000 + (72 million requests / 20 for WebSocket message billing ratio) = 3.75 million billing request.
- 3.75 million requests - included 1 million requests = 2,750,000 billable requests.
- (rounded) 3,000,000 requests x $0.15 / 1,000,000 = $0.45.
Compute Duration:
- 100 Durable Objects * 60 seconds * 60 minutes * 8 hours * 30 days = 86,400,000 seconds.
- 86,400,000 seconds * 128 MB / 1 GB = 11,059,200 GB-s.
- 11,059,200 GB-s - included 400,000 GB-s = 10,659,200 GB-s
- (rounded) 11,000,000 GB-s x $12.50 / 1,000,000 = $137.50.
Estimated total: $0.45 (requests) + $137.50 (compute duration) + minimum $5/mo usage = $142.95 per month.
Example 3
This example represents a horizontally scaled Durable Objects based application using WebSockets to communicate user-specific state to a single client connected to each Durable Object.
- 100 Durable Objects each have a single WebSocket connection established to each of them.
- Clients sent one message every second of the month so that the Durable Objects were active for the entire month.
In this scenario, the estimated monthly cost would be calculated as:
Requests:
- 100 WebSocket connection requests.
- 1 message per second * 100 connections * 60 seconds * 60 minutes * 24 hours * 30 days = 259,200,000 WebSocket message requests.
- 100 + (259.2 million requests / 20 for WebSocket billing ratio) = 12,960,100 requests.
- 12,960,100 requests - included 1 million requests = 11,960,100 billable requests.
- (rounded) 12,000,000 requests x $0.15 / 1,000,000 = $1.80.
Compute Duration:
- 100 Durable Objects * 60 seconds * 60 minutes * 24 hours * 30 days = 259,200,000 seconds
- 259,200,000 seconds * 128 MB / 1 GB = 33,177,600 GB-s
- 33,177,600 GB-s - included 400,000 GB-s = 32,777,600 GB-s
- (rounded) 33,000,000 GB-s x $12.50 / 1,000,000 = $412.50
Estimated total: $1.80 (requests) + $412.50 (compute duration) + minimum $5/mo usage = $419.30 per month
Example 4
This example represents a moderately trafficked Durable Objects based application using WebSocket Hibernation to broadcast game, chat or real-time user state across connected clients:
- 100 Durable Objects each have 100 Hibernatable WebSocket connections established to each of them.
- Clients send one message per minute, and it takes 10ms to process a single message in the
webSocketMessage()handler. Since each Durable Object handles 100 WebSockets, cumulatively each Durable Object will be actively executing JS for 1 second each minute (100 WebSockets * 10ms).
In this scenario, the estimated monthly cost would be calculated as:
Requests:
- 100 WebSocket connections * 100 Durable Objects to establish the WebSockets = 10,000 initial WebSocket connection requests.
- 100 messages per minute1 * 100 Durable Objects * 60 minutes * 24 hours * 30 days = 432,000,000 requests.
- 10,000 + (432 million requests / 20 for WebSocket billing ratio) = 21,610,000 requests.
- 21,610,000 requests - included 1 million requests = 20,610,000 billable requests.
- (rounded) 21,000,000 requests x $0.15 / 1,000,000 = $3.15.
Compute Duration:
- 100 Durable Objects * 1 second2 * 60 minutes * 24 hours * 30 days = 4,320,000 seconds
- 4,320,000 seconds * 128 MB / 1 GB = 552,960 GB-s
- 552,960 GB-s - included 400,000 GB-s = 152,960 GB-s
- (rounded) 1,000,000 GB-s x $12.50 / 1,000,000 = $12.50
Estimated total: $3.15 (requests) + $12.50 (compute duration) + minimum $5/mo usage = $20.65 per month
1 100 messages per minute comes from the fact that 100 clients connect to each DO, and each sends 1 message per minute.
2 The example uses 1 second because each Durable Object is active for 1 second per minute. This can also be thought of as 432 million requests that each take 10 ms to execute (4,320,000 seconds).
Frequently Asked Questions
When does a Durable Object incur duration charges?
A Durable Object incurs duration charges when it is actively executing JavaScript — either handling a request or running event handlers — or when it is idle but does not meet the conditions for hibernation. An idle Durable Object that qualifies for hibernation does not incur duration charges, even during the brief window before the runtime hibernates it.
Once an object has been evicted from memory, the next time it is needed, it will be recreated (calling the constructor again).
There are several factors that can prevent a Durable Object from hibernating and cause it to continue incurring duration charges.
Find more information in Lifecycle of a Durable Object.
Does an empty table / SQLite database contribute to my storage?
Yes, although minimal. Empty tables can consume at least a few kilobytes, based on the number of columns (table width) in the table. An empty SQLite database consumes approximately 12 KB of storage.
Does metadata stored in Durable Objects count towards my storage?
All writes to a SQLite-backed Durable Object stores nominal amounts of metadata in internal tables in the Durable Object, which counts towards your billable storage.
The metadata remains in the Durable Object until you call deleteAll().
Limits
As of Nov 3, 2026, from Cloudflare's docs, last updated there Oct 29, 2026. Licensed CC BY 4.0; navigation removed.
Durable Objects are a special kind of Worker, so Workers limits also apply. Limits that depend on your Workers plan are identified on that page. This page also covers Durable Object storage, CPU, and outbound HTTP request body size limits.
SQLite-backed Durable Objects general limits
| Feature | Limit |
|---|---|
| Number of Objects | Unlimited (within an account or of a given class) |
| Maximum Durable Object classes (per account) | 500 (Workers Paid) / 100 (Free) 1 |
| Storage per account | Unlimited (Workers Paid) / 5GB (Free) 2 |
| Storage per class | Unlimited 3 |
| Storage per Durable Object | 10 GB 3 |
| Key size | Key and value combined cannot exceed 2 MB |
| Value size | Key and value combined cannot exceed 2 MB |
| WebSocket message size | 32 MiB (only for received messages) |
| CPU per request | 30 seconds (default) / configurable to 5 minutes of active CPU time 4 |
| Simultaneous outgoing connections/request | 6 (same as Workers) |
SQL storage limits
For Durable Object classes with SQLite storage these SQL limits apply:
| SQL | Limit |
|---|---|
| Maximum number of columns per table | 100 |
| Maximum number of rows per table | Unlimited (excluding per-object storage limits) |
Maximum string, BLOB or table row size |
2 MB |
| Maximum SQL statement length | 100 KB |
| Maximum bound parameters per query | 100 |
| Maximum arguments per SQL function | 32 |
Maximum characters (bytes) in a LIKE or GLOB pattern |
50 bytes |
Key-value backed Durable Objects general limits
Note
Durable Objects are available both on Workers Free and Workers Paid plans.
- Workers Free plan: Only Durable Objects with SQLite storage backend are available.
- Workers Paid plan: Durable Objects with the SQLite storage backend are available. The key-value storage backend is only available to accounts that already have a key-value-backed namespace.
If you wish to downgrade from a Workers Paid plan to a Workers Free plan, you must first ensure that you have deleted all Durable Object namespaces with the key-value storage backend.
| Feature | Limit for class with key-value storage backend |
|---|---|
| Number of Objects | Unlimited (within an account or of a given class) |
| Maximum Durable Object classes (per account) | 500 (Workers Paid) / 100 (Free) 5 |
| Storage per account | 50 GB (can be raised by contacting Cloudflare) 6 |
| Storage per class | Unlimited |
| Storage per Durable Object | Unlimited |
| Key size | 2 KiB (2048 bytes) |
| Value size | 128 KiB (131072 bytes) |
| WebSocket message size | 32 MiB (only for received messages) |
| CPU per request | 30s (including WebSocket messages) 7 |
| Simultaneous outgoing connections/request | 6 (same as Workers) |
Need a higher limit?
To request an adjustment to a limit, complete the Limit Increase Request Form ↗︎. If the limit can be increased, Cloudflare will contact you with next steps.
Outbound HTTP request body size
Cloudflare limits each HTTP request body a Durable Object sends to an external service with fetch() to 100 MiB by default. Requests exceeding this limit can fail with 413 Payload Too Large.
| Limit | Default |
|---|---|
| Outbound HTTP request body size | 100 MiB (104,857,600 bytes) |
This limit applies to each request body, including encoding and multipart form fields. It does not limit the total size of a file uploaded through separate requests. The destination service can impose additional limits.
The Maximum Upload Size setting for your application's custom domain does not control this limit. A larger upload accepted by your domain can still be rejected when your Container or Durable Object sends it to another service.
For larger uploads, use the destination's multipart or resumable upload API. Keep each request body below the limit. If you already use multipart uploads, reduce the part size. Streaming, HTTP chunked transfer encoding, and multipart/form-data do not bypass the limit on a single request body.
To request a higher outbound limit, contact your account team or Cloudflare Support. Specify that the request concerns outbound HTTP uploads from Containers or Durable Objects. Increases are subject to review.
Include the following information:
- The account ID and Worker name for the affected workload.
- The Container instance ID or Durable Object namespace and ID.
- The destination hostname.
- The failing request body size in bytes and the requested limit.
- The failure timestamp, relevant error logs, and a minimal reproduction.
Frequently Asked Questions
How much work can a single Durable Object do?
Durable Objects can scale horizontally across many Durable Objects. Each individual Object is inherently single-threaded.
- An individual Object has a soft limit of 1,000 requests per second. You can have an unlimited number of individual objects per namespace.
- A simple storage
get()on a small value that directly returns the response may realize a higher request throughput compared to a Durable Object that (for example) serializes and/or deserializes large JSON values. - Similarly, a Durable Object that performs multiple
list()operations may be more limited in terms of request throughput.
A Durable Object that receives too many requests will, after attempting to queue them, return an overloaded error to the caller.
How many Durable Objects can I create?
Durable Objects are designed such that the number of individual objects in the system do not need to be limited, and can scale horizontally.
- You can create and run as many separate Durable Objects as you want within a given Durable Object namespace.
- There are no limits for storage per account when using SQLite-backed Durable Objects on a Workers Paid plan.
- Each SQLite-backed Durable Object has a storage limit of 10 GB on a Workers Paid plan.
- Refer to Durable Object limits for more information.
Can I increase Durable Objects' CPU limit?
Durable Objects are Worker scripts, and have the same per invocation CPU limits as any Workers do. Note that CPU time is active processing time: not time spent waiting on network requests, storage calls, or other general I/O, which don't count towards your CPU time or Durable Objects compute consumption.
By default, the maximum CPU time per Durable Objects invocation (HTTP request, WebSocket message, or Alarm) is set to 30 seconds, but can be increased for all Durable Objects associated with a Durable Object definition by setting limits.cpu_ms in your Wrangler configuration:
{
// ...rest of your configuration...
"limits": {
"cpu_ms": 300000, // 300,000 milliseconds = 5 minutes
},
// ...rest of your configuration...
}
[limits]
cpu_ms = 300_000
What happens when a Durable Object exceeds its storage limit?
When a SQLite-backed Durable Object reaches its maximum storage limit (10 GB on Workers Paid, or 1 GB on the Free plan), write operations (such as INSERT, UPDATE, or calls to the put() and sql.exec() storage APIs) will fail with the following error:
database or disk is full: SQLITE_FULL
Read operations (such as SELECT queries, get(), and list() calls) will continue to work, and DELETE operations will also succeed so that you can remove data to free up space.
To handle this error in your Durable Object, catch the exception thrown by the storage API:
try {
this.ctx.storage.sql.exec(
"INSERT INTO my_table (key, value) VALUES (?, ?)",
key,
value,
);
} catch (e) {
if (e.message.includes("SQLITE_FULL")) {
// Storage limit reached — reads and deletes still work
// Consider deleting old data or returning a meaningful error to the caller
}
throw e;
}
Wall time limits by invocation type
Wall time (also called wall-clock time) is the total elapsed time from the start to end of an invocation, including time spent waiting on network requests, I/O, and other asynchronous operations. This is distinct from CPU time, which only measures time the CPU spends actively executing your code.
The following table summarizes the wall time limits for different types of Worker invocations across the developer platform:
| Invocation type | Wall time limit | Details |
|---|---|---|
| Incoming HTTP request | Unlimited | No hard limit while the client remains connected. Workers requests are subject to the grace period for runtime updates. A Worker that is still streaming a response body remains active. waitUntil() extends execution for up to 30 seconds after the response or disconnect. |
| Cron Triggers | 15 minutes | Scheduled Workers have a maximum wall time of 15 minutes per invocation. |
| Queue consumers | 15 minutes | Each consumer invocation has a maximum wall time of 15 minutes. |
| Durable Object alarm handlers | 15 minutes | Alarm handler invocations have a maximum wall time of 15 minutes. |
| Durable Objects (RPC / HTTP) | Unlimited | No hard limit while the caller stays connected to the Durable Object. Durable Objects remain active while a request, RPC call, response stream, WebSocket, or pending I/O is in flight. |
| Workflows (per step) | Unlimited | Each step can run for an unlimited wall time. Individual steps are subject to the configured CPU time limit. |
Footnotes
- Identical to the Workers script limit. ↩
- Durable Objects both bills and measures storage based on a gigabyte
(1 GB = 1,000,000,000 bytes) and not a gibibyte (GiB).
↩ - Accounts on the Workers Free plan are limited to 5 GB total Durable Objects storage. ↩ ↩2
- Each incoming HTTP request or WebSocket message resets the remaining available CPU time to 30 seconds. This allows the Durable Object to consume up to 30 seconds of compute after each incoming network request, with each new network request resetting the timer. If you consume more than 30 seconds of compute between incoming network requests, there is a heightened chance that the individual Durable Object is evicted and reset. CPU time per request invocation can be increased. ↩
- Identical to the Workers script limit. ↩
- Durable Objects both bills and measures storage based on a gigabyte
(1 GB = 1,000,000,000 bytes) and not a gibibyte (GiB).
↩ - Each incoming HTTP request or WebSocket message resets the remaining available CPU time to 30 seconds. This allows the Durable Object to consume up to 30 seconds of compute after each incoming network request, with each new network request resetting the timer. If you consume more than 30 seconds of compute between incoming network requests, there is a heightened chance that the individual Durable Object is evicted and reset. CPU time per request invocation can be increased. ↩
Timeline
October 2026
- Durable Objects now defer code updates by default
Durable Objects can stay active across requests, allowing you to run long-running agents, maintain long-lived WebSocket connections and coordinate state across many clients. This is possible because each Durable Object is globally unique, and this means it must run only one version of your code at a time. Previously, when you deployed a change to your Durable Objects code, that change would be ap…
- Increased Errors for Durable Objects and Downstream Services in Eastern North America (ENAM) Incident
Minor impact. Resolved Oct 29, 2026, 16:50 UTC.
- Increased Durable Objects, D1 and Workflows Error Rates Incident
Minor impact. Resolved Oct 29, 2026, 16:33 UTC.
- Issues with Durable Objects availability in Eastern Europe Incident
Minor impact. Resolved Oct 29, 2026, 11:47 UTC.
- Increased latency and error rate for R2 in ENAM Incident
Minor impact. Resolved Oct 28, 2026, 21:12 UTC.
- Increased Errors for Durable Objects in the Eastern North America region Incident
Minor impact. Resolved Oct 28, 2026, 11:10 UTC.
- Increased Errors for Durable Objects in the Eastern North America region Incident
Minor impact. Resolved Oct 28, 2026, 03:28 UTC.
- Elevated error rates for Durable Objects in Western Europe Incident
Minor impact. Resolved Oct 23, 2026, 00:09 UTC.
- Elevated Error Rate for Durable Objects in Lisbon Incident
Minor impact. Resolved Oct 22, 2026, 00:35 UTC.
- Elevated Errors for R2 and Durable Objects in ENAM Incident
Major impact. Resolved Oct 21, 2026, 21:21 UTC.
- Cutting our inference bill by 68% by being obsessive about optimization Blog
When our AI code reviewer's cost per run doubled, we dug into the token usage to find out why. Learn how we used prompt caching and intelligent model routing to slash our inference bill by 68% while speeding up reviews.
- Pending I/O operations allow Durable Objects to continue long-running work without a connected client
Durable Objects remain active while handling a request from a connected client. This change applies when no client is connected, such as when an agent continues a submitted job after its client disconnects. This behavior is the default for Workers with a compatibility date of 2026-10-01 or later. To use it with an earlier date, add the durable_object_io_tasks_prevent_eviction compatibility flag.…
September 2026
- Durable Object name search now supports 128 characters
Durable Object name searches in the Cloudflare dashboard now accept up to 128 characters, up from 20. Search results and recent invocation lists show up to 128 characters before being truncated with an ellipsis. This limit applies to the object filter on the Metrics tab and object search in Data Studio. For more information, refer to Metrics and analytics and Data Studio.
- Workers traces now automatically include JavaScript RPC session spans
Workers traces can now follow JavaScript RPC calls across Worker boundaries and into Durable Objects. Previously, a trace stopped at the caller's RPC boundary. The dashboard now shows the caller-side session and method calls alongside the callee invocation, nested calls, and callbacks into another Worker. A session span covers the lifetime of a caller-side session and groups calls that reuse it.…
August 2026
- Durable Objects can use up to ten Dynamic Workers concurrently
Durable Objects can have up to ten distinct Dynamic Workers with in-flight requests, increased from four. This limit applies across all concurrent requests to the same Durable Object because they share an input/output (I/O) context. Other Workers can have up to four distinct Dynamic Workers with in-flight requests per request. Multiple in-flight requests to the same Dynamic Worker count as one to…
- Prevent Durable Object alarm retries when using `ctx.abort()`
By default, an alarm interrupted by ctx.abort() retries after the Durable Object resets. Pass { retryAlarm: false } when the alarm should stop instead: src/index.jsjsimport { DurableObject } from "cloudflare:workers"; export class CleanupTask extends DurableObject { async alarm() { await this.ctx.storage.deleteAll(); this.ctx.abort("Cleanup complete", { retryAlarm: false }); } } src/index.tstsimp…
- View deployments for Durable Objects in the dashboard
Durable Object namespaces now have a Deployments tab in the Cloudflare dashboard, showing the versions of the backing Worker that are currently live and the traffic split between them. Go to Durable Objects ↗ A Durable Object namespace is backed by a Worker script, so its deployments are the same as that Worker's deployments. Previously, checking on a gradual deployment in progress for a Durable…
July 2026
- Inspect Worker startup performance with Wrangler
wrangler check startup now reports your Worker's raw and compressed bundle sizes. It also summarizes local CPU activity during startup directly in your terminal. Large bundles and costly startup work can introduce cold-start latency, so use this command to find code and large dependencies that slow your Worker before it handles requests. The summary includes sampled, active, garbage collection, a…
- Filter Durable Object logs and traces by instance ID
Workers Logs and OpenTelemetry spans for Durable Object requests include the Durable Object instance ID. Use $workers.durableObjectId to filter logs for a specific instance. Root and child spans include the same ID in cloudflare.durable_object.id. Use these fields to isolate a specific instance and correlate its logs and traces. For more information, refer to Durable Objects metrics and analytics…
- View total SQLite storage for Durable Object namespaces
You can now monitor the total SQLite storage used by a Durable Object namespace over time in the Cloudflare dashboard. The new Total storage chart shows the maximum storage reported during each hour. This helps you identify storage growth, validate data cleanup, and investigate unexpected usage. Go to Durable Objects ↗ The chart appears only for SQLite-backed Durable Object namespaces. It does no…
- New Durable Object namespaces must use the SQLite storage backend
If your account does not already have a key-value (KV) backed Durable Object namespace, you can no longer create new ones. New Durable Object namespaces must use the SQLite storage backend, which has been recommended for all new Durable Objects since it became generally available ↗︎ in 2024. Create a new class with a new_sqlite_classes migration: { "$schema": "./node_modules/wrangler/config-schem…
- Declare Durable Object class lifecycle with `exports`
A new declarative exports field in your Wrangler configuration file replaces the imperative migrations array for managing Durable Object class lifecycle. Instead of writing an ordered list of migration steps with unique tags, you declare each Durable Object class your Worker exports and Cloudflare compares that against what's already deployed to determine what Durable Object state needs to be cre…
June 2026
- Track memory usage for Workers and Durable Objects in the dashboard
You can now monitor how much memory your Workers and Durable Objects consume across invocations with the new Memory Usage chart in the Workers Metrics tab, broken down by P50, P90, P99, and P999 percentiles. Memory usage measures the V8 isolate memory at the time of each invocation, subject to the 128 MB per-isolate limit — a single isolate can handle many concurrent requests and shares memory ac…
- New `us` jurisdiction for Durable Objects
Durable Objects now supports a us jurisdiction, letting you create Durable Objects that only run and store data within the United States. Use the us jurisdiction when you need to keep a Durable Object's compute and storage inside the United States to meet data residency requirements. Create a namespace restricted to the us jurisdiction the same way as any other jurisdiction: // Worker export defa…
- Test Durable Object eviction with new cloudflare:test helpers
The @cloudflare/vitest-pool-workers package now includes evictDurableObject and evictAllDurableObjects test helpers, exported from cloudflare:test. These helpers let you test how a Durable Object behaves across evictions, simulating the production lifecycle where an idle Durable Object can be evicted from memory. For more context, refer to Lifecycle of a Durable Object. import { evictDurableObjec…
- New Asia-Pacific location hints: apac-ne and apac-se
Durable Objects now supports two new location hints for Asia-Pacific: apac-ne (Northeast Asia-Pacific) and apac-se (Southeast Asia-Pacific). Use apac-ne or apac-se when you want finer-grained placement within Asia-Pacific rather than the broader apac hint. Use the new hints the same way as any other locationHint: // Northeast Asia-Pacific (Japan, Korea, etc.) const stubNE = env.MY_DURABLE_OBJECT.…
- Outbound connections keep Durable Objects alive
Durable Objects now remain alive for the duration of active outbound connections created via connect() or an outbound WebSocket. Previously, a Durable Object would be evicted after 70-140 seconds of no incoming traffic, even if the object had an open outbound connection, which is a common pattern when streaming responses from a large language model (LLM) over TCP or an outbound WebSocket. With th…
- Filter Durable Objects metrics by object ID or name
You can now filter the Metrics tab for a Durable Objects namespace by an individual Durable Object's ID or name in the Cloudflare dashboard. Previously, metrics charts only showed aggregate, namespace-level data, making it difficult to isolate the behavior of a specific object. Go to Durable Objects ↗ Start typing an ID or name into the filter and select a match from the autocomplete dropdown. Th…
- Billable usage and budget alerts now in product sidebars
Pay-as-you-go customers can now view billable usage and create budget alerts directly from the product overview pages for Workers & Pages, D1, R2, Workers KV, Queues, Vectorize, Durable Objects, and Containers. A new sidebar widget shows current-period spend and the billing cycle date range, alongside a button to create a budget alert. The widget pulls from the same data as the Billable Usage das…
March 2026
- Access Durable Object jurisdiction via `ctx.id.jurisdiction`
ctx.id.jurisdiction inside a Durable Object now reports the jurisdiction the object was created in — for example "eu" when accessed through env.MY_DURABLE_OBJECT.jurisdiction("eu") — so you can make region-aware decisions without passing the jurisdiction through method arguments or persisting it in storage. For the full list of ID-construction paths that preserve jurisdiction, refer to the Durabl…
- Access Durable Object name via `ctx.id.name`
When your Worker accesses a Durable Object via idFromName() or getByName(), the same name is now available on ctx.id.name inside the object — no need to pass it through method arguments or persist it in storage. This brings the runtime behavior in line with the Workers runtime types. This is especially useful for alarms, where there is no calling client to pass the name as an argument. When an al…
February 2026
- deleteAll() now deletes Durable Object alarm
deleteAll() now deletes a Durable Object alarm in addition to stored data for Workers with a compatibility date of 2026-02-24 or later. This change simplifies clearing a Durable Object's storage with a single API call. Previously, deleteAll() only deleted user-stored data for an object. Alarm usage stores metadata in an object's storage, which required a separate deleteAlarm() call to fully clean…
December 2025
- New Best Practices guide for Durable Objects
A new Rules of Durable Objects guide is now available, providing opinionated best practices for building effective Durable Objects applications. This guide covers design patterns, storage strategies, concurrency, and common anti-patterns to avoid. Key guidance includes: Design around your "atom" of coordination — Create one Durable Object per logical unit (chat room, game session, user) instead o…
- Billing for SQLite Storage
Storage billing for SQLite-backed Durable Objects will be enabled in January 2026, with a target date of January 7, 2026 (no earlier). To view your SQLite storage usage, go to the Durable Objects page Go to Durable Objects ↗ If you do not want to incur costs, please take action such as optimizing queries or deleting unnecessary stored data in order to reduce your SQLite storage usage ahead of the…
October 2025
- Workers WebSocket message size limit increased from 1 MiB to 32 MiB
Workers, including those using Durable Objects and Browser Rendering, may now process WebSocket messages up to 32 MiB in size. Previously, this limit was 1 MiB. This change allows Workers to handle use cases requiring large message sizes, such as processing Chrome Devtools Protocol messages. For more information, please see the Durable Objects startup limits.
- View and edit Durable Object data in UI with Data Studio (Beta)
You can now view and write to each Durable Object's storage using a UI editor on the Cloudflare dashboard. Only Durable Objects using SQLite storage can use Data Studio. Go to Durable Objects ↗ Data Studio unlocks easier data access with Durable Objects for prototyping application data models to debugging production storage usage. Before, querying your Durable Objects data required deploying a Wo…
August 2025
- New getByName() API to access Durable Objects
You can now create a client (a Durable Object stub) to a Durable Object with the new getByName method, removing the need to convert Durable Object names to IDs and then create a stub. // Before: (1) translate name to ID then (2) get a client const objectId = env.MY_DURABLE_OBJECT.idFromName("foo"); // or .newUniqueId() const stub = env.MY_DURABLE_OBJECT.get(objectId); // Now: retrieve client to D…
June 2025
- @cloudflare/actors library - SDK for Durable Objects in beta
The new @cloudflare/actors ↗︎ library is now in beta! The @cloudflare/actors library is a new SDK for Durable Objects and provides a powerful set of abstractions for building real-time, interactive, and multiplayer applications on top of Durable Objects. With beta usage and feedback, @cloudflare/actors will become the recommended way to build on Durable Objects and draws upon Cloudflare's experie…
May 2025
- Durable Objects are now supported in Python Workers
You can now create Durable Objects using Python Workers. A Durable Object is a special kind of Cloudflare Worker which uniquely combines compute with storage, enabling stateful long-running applications which run close to your users. For more info see here. You can define a Durable Object in Python in a similar way to JavaScript: from workers import DurableObject, Response, WorkerEntrypoint from…
April 2025
- Durable Objects on Workers Free plan
Durable Objects can now be used with zero commitment on the Workers Free plan allowing you to build AI agents with Agents SDK, collaboration tools, and real-time applications like chat or multiplayer games. Durable Objects let you build stateful, serverless applications with millions of tiny coordination instances that run your application code alongside (in the same thread!) your durable storage…
- SQLite in Durable Objects GA with 10GB storage per object
SQLite in Durable Objects is now generally available (GA) with 10GB SQLite database per Durable Object. Since the public beta ↗︎ in September 2024, we've added feature parity and robustness for the SQLite storage backend compared to the preexisting key-value (KV) storage backend for Durable Objects. SQLite-backed Durable Objects are recommended for all new Durable Object classes, using new_sqlite…