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.
| 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) |
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 |
| 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) |
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.
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.
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.
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_000When 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_FULLRead 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 (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. |
-
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. ↩