Durable Objects local data initialization
For Durable Objects, there are no CLI commands to populate them with local data. To add data to Durable Objects during local development, you must write application code that creates Durable Object instances and calls methods on them that store state. This typically involves creating development endpoints or test routes that initialize Durable Objects with desired data.
Bulk upload to local KV
Use the command: wrangler kv bulk put <FILENAME.json> --binding=<BINDING> --local to bulk upload data from a JSON file to a local KV namespace.
Add single KV key-value pair
Use the command: wrangler kv key put <KEY> <VALUE> --binding=<BINDING> --local to add a single key-value pair to a local KV namespace. This syntax requires Wrangler version 3.60.0 or later. Earlier versions use the kv:... syntax.
Execute SQL file in local D1
Use the command: wrangler d1 execute <DATABASE_NAME> --file=./schema.sql --local to execute SQL statements from a file against a local D1 database.
Example R2 remote binding configuration
To configure R2 bucket as remote binding, add to wrangler.jsonc: { "r2_buckets": [ { "bucket_name": "screenshots-bucket", "binding": "screenshots_bucket", "remote": true } ] }
Example environment-specific R2 binding for staging
To use different R2 buckets for production and staging environments, configure in wrangler.jsonc under 'env' section: production uses 'screenshots-bucket' without remote flag, staging uses 'preview-screenshots-bucket' with 'remote: true'. Then run 'wrangler dev -e staging' to connect to staging bucket.
Example Browser Run remote binding configuration
To configure Browser Run as remote binding, add to wrangler.jsonc: { "browser": { "binding": "MY_BROWSER", "remote": true } }
Example Workers AI remote binding configuration
To configure Workers AI as remote binding, add to wrangler.jsonc: { "ai": { "binding": "AI", "remote": true } }
Example Vectorize remote binding configuration
To configure Vectorize as remote binding, add to wrangler.jsonc: { "vectorize": [ { "binding": "MY_VECTORIZE_INDEX", "index_name": "my-prod-index", "remote": true } ] }
Example mTLS remote binding configuration
To configure mTLS as remote binding, add to wrangler.jsonc: { "mtls_certificates": [ { "binding": "MY_CLIENT_CERT_FETCHER", "certificate_id": "<YOUR_UPLOADED_CERT_ID>", "remote": true } ] }
Example Images remote binding configuration
To configure Images as remote binding, add to wrangler.jsonc: { "images": { "binding": "IMAGES", "remote": true } }
Example maybeStartOrUpdateRemoteProxySession with KV binding
Example TypeScript code using maybeStartOrUpdateRemoteProxySession with single KV binding: Declares remoteProxySessionDetails and mf variables, defines startOrUpdateDevSession async function that calls maybeStartOrUpdateRemoteProxySession with bindings object containing MY_KV with type 'kv_namespace', id 'kv-id', and remote true. Creates or updates Miniflare instance with kvNamespaces config using remoteProxyConnectionString from session details.
Example Dispatch Namespace remote binding configuration
To configure Dispatch Namespace as remote binding for Workers for Platforms, add to wrangler.jsonc: { "dispatch_namespaces": [ { "binding": "DISPATCH_NAMESPACE", "namespace": "testing", "remote": true } ] }
AI bindings always run remotely by default
AI bindings connect to remote resources by default and do not have local simulations. There is no way to configure them to run locally.
Remote bindings supported by Wrangler, Vite plugin, and vitest-pool-workers
Remote bindings are supported by Wrangler CLI, Cloudflare Vite plugin, and the @cloudflare/vitest-pool-workers package.
Recommended remote bindings for specific services
The following bindings are recommended to have 'remote: true' because they rely on Cloudflare infrastructure or have complex backends not fully simulated locally: Browser Run, Workers AI, Vectorize, mTLS, Images (limited local simulation), and Dispatch Namespaces.
Bindings use exact same API calls in local and production
During local development, Worker code interacts with bindings using the exact same API calls (such as env.MY_KV.put()) as it would in a deployed environment. Local resources are initially empty but can be populated with data.
Remote bindings configuration
Remote bindings are configured by setting 'remote: true' in the binding definition in wrangler.jsonc. This routes binding operations to deployed resources instead of local simulations. Worker code still executes locally; only the underlying resources the bindings connect to change.
wrangler dev --local flag disables all remote bindings
Use 'wrangler dev --local' to temporarily disable all remote bindings during local development and connect only to local resource simulations.
Remote bindings with Workers Environments
Remote bindings work with Workers Environments to protect production data. Create a development or staging environment and specify different resources in Wrangler configuration than production. Use 'wrangler dev -e staging' to run with environment-specific bindings.
Browser Run requires remote: true configuration
Browser Run binding requires 'remote: true' in wrangler.jsonc to interact with a real headless browser. There is no local simulation for Browser Run. If not specified, Cloudflare will issue a warning.
Workers AI requires remote: true or produces error
Workers AI binding requires 'remote: true' in wrangler.jsonc to utilize actual AI models on Cloudflare's network. If remote is set to false, Cloudflare produces an error. If omitted, Cloudflare connects to remote resource and issues a warning.
Vectorize requires remote: true for accurate vector search
Vectorize binding should have 'remote: true' in wrangler.jsonc to connect to production Vectorize indexes for accurate vector search and similarity operations. There is no local simulation for Vectorize.
mTLS requires remote: true for certificate validation
mTLS binding should have 'remote: true' in wrangler.jsonc to verify certificate exchange and validation work as expected. There is no local simulation for mTLS bindings.
Images binding has limited local simulation
Images binding local simulation is limited with only a subset of features. Use 'remote: true' in wrangler.jsonc to connect to high-fidelity Images API and verify all transformations work as expected.
Dispatch Namespaces can use remote: true for Workers for Platforms
Workers for Platforms users can configure 'remote: true' in dispatch namespace binding definitions to run dynamic dispatch Workers locally while connecting to remote dispatch namespace binding, allowing testing against real deployed user Workers.
Unsupported remote bindings: Durable Objects, Workflows, vars, Secrets, Static Assets, Version Metadata, Analytics Engine, Hyperdrive, Rate Limiting
The following binding types do not support remote connections (remote: true) and will always use local simulations or local values: Durable Objects, Workflows, Environment Variables (vars), Secrets, Static Assets, Version Metadata, Analytics Engine, Hyperdrive, and Rate Limiting. Using remote: true for these binding types will produce an error.
Using remote resources with Durable Objects and Workflows
Although Durable Object and Workflow bindings cannot be remote, they can interact with remote resources during local development through two patterns: (1) Local Durable Objects/Workflows with remote bindings enabled in configuration, or (2) Accessing remote Durable Objects/Workflows via service bindings by deploying a Worker with those definitions and using a remote service binding in the local Worker.
Remote bindings important considerations
When using remote bindings: (1) If Worker is protected by Cloudflare Access, Wrangler must authenticate with Access. (2) Write/delete/update operations affect actual data in targeted Cloudflare resources. (3) Standard operational costs are incurred for interactions with remote services. (4) Expect network latency for remote operations.
Wrangler programmatic APIs for remote bindings
Wrangler provides APIs for tooling authors: startRemoteProxySession (starts proxy session for remote bindings), unstable_convertConfigBindingsToStartWorkerBindings (converts binding definitions from Unstable_Config to StartDevWorkerInput format), and maybeStartOrUpdateRemoteProxySession (convenience wrapper to start or update proxy session).
startRemoteProxySession API returns object with ready, dispose, updateBindings, and remoteProxyConnectionString
startRemoteProxySession returns object with: ready (Promise<void> that resolves when session is ready), dispose (() => Promise<void> to stop session), updateBindings ((bindings: StartDevWorkerInput['bindings']) => Promise<void> to update session bindings), and remoteProxyConnectionString (string to pass to Miniflare for remote binding access).
maybeStartOrUpdateRemoteProxySession accepts bindings or config path
maybeStartOrUpdateRemoteProxySession takes object containing either path to Wrangler configuration with potential target environment, or Worker name with bindings. Also takes current proxy session details (can be null) and optionally auth data. Returns proxy session details if started/updated, or null if no proxy session needed.
WebSocket message output gate enforcement
As of 2022-02-11, WebSocket message sends now properly respect Durable Object output gates. WebSockets will never send a message under the assumption a storage write succeeded unless the write actually succeeded.
R2 GET range parameter
As of 2022-06-24, R2 GET requests made with the range option now contain the returned range in the GetObject's range parameter.
Durable Object alarms no longer require explicit flag
As of 2022-06-18, the durable_object_alarms flag no longer needs to be explicitly provided to use DO alarms.
R2 conditional PUT requests fix
As of 2022-12-16, conditional PUT requests have been fixed in the R2 bindings API.
Queues do not accept undefined values
As of 2022-12-02, Queues no longer support calling send() with an undefined JavaScript value as the message.
R2 multipart uploads support
As of 2022-11-30, the R2 binding API has been extended to include support for multipart uploads.
DurableObjectStorage sync method
As of 2022-10-21, DurableObjectStorage has a new method sync() that provides a way for a Worker to wait for its writes, including those performed with allowUnconfirmed, to be synchronized with storage.
R2 onlyIf conditional uploads in put bindings
As of 2022-09-16, R2 put bindings options can have an onlyIf field similar to get that performs a conditional upload.
R2 multiple key deletion
As of 2022-09-16, the R2 bindings allow deleting multiple keys at once.
R2 checksum support
As of 2022-09-16, R2 put options support SHA-1, SHA-256, SHA-384, and SHA-512 checksums. User-specified object checksums are now available in R2 get/head bindings response. MD5 is included by default for non-multipart uploaded objects.
R2 range requests with Headers
As of 2022-08-12, a Headers object with the range header can be used for range requests within R2GetOptions for the get R2 binding.
R2 onlyIf conditional headers second granularity
As of 2022-08-12, when headers are used for onlyIf within R2GetOptions for the get R2 binding, they now correctly compare against second granularity. The secondsGranularity option can be passed when constructing options by hand to specify this behavior.
R2 exception error code in message
As of 2022-05-26, R2 exceptions being thrown now have the error code appended in the message in parentheses.
Durable Object setAlarm without alarm handler throws
As of 2022-05-19, calling setAlarm() in a Durable Object with no alarm() handler implemented will throw. Calling getAlarm() when no alarm() handler is currently implemented will return null.
R2 range request formats
As of 2022-05-19, R2 bindings support ranges with an offset and optional length, a length and optional offset, or a suffix (returns last N bytes).
R2 onlyIf precondition failure returns object without body
As of 2022-05-12, in R2 bindings, if the onlyIf condition results in a precondition failure or not modified result, the object is returned without a body instead of returning null.
Durable Object storage list startAfter option
As of 2022-05-12, the list() method in the Durable Object storage API supports a startAfter option.
R2 public beta bindings default
As of 2022-04-29, R2 public beta bindings are the default regardless of compat date or flags. Internal beta bindings customers should transition to public beta bindings. A back compatibility flag is available if immediate transition is not possible.
Durable Object write unit billing includes key size
As of 2022-03-11, the key size is counted when determining write units charged for a Durable Object single-key put(). This may result in future writes costing one write unit more than past writes if the key is large enough to bump total write size above the 4096 byte billing threshold.
Durable Object ID in constructor
As of 2021-02-11, a Durable Object's ID is provided to it in its constructor and can be accessed via state.id.
Durable Object storage max value size
As of 2021-12-10, the max value size in Durable Object storage is 128 KiB, up from 32 KiB.
Durable Object constructor I/O support
As of 2021-07-16, Durable Object constructors may initiate I/O, such as fetch() calls.
Durable Object blockConcurrencyWhile API
As of 2021-07-16, Durable Objects have a state.blockConcurrencyWhile() API useful for delaying request and event delivery while performing critical state-affecting tasks, such as start-up initialization.
Durable Object transaction return value
As of 2021-07-16, in Durable Objects, the callback passed to storage.transaction() can return a value, which propagates as the transaction() return value.
Durable Object exceeding CPU time discards object
As of 2021-04-23, when a Durable Object exceeds its CPU time limit, the entire object is discarded and recreated. Previously subrequests could continue using the same object, which was dangerous.
Durable Object code update invalidates stubs
As of 2021-04-23, when a Durable Object's code is updated or isolate is reset due to exceeding memory limit, all stubs pointing to the object are invalidated and must be recreated.
Durable Object memory limit exception message
As of 2021-04-23, when a Durable Object isolate exceeds its memory limit, an exception with an explanatory message is thrown to the caller instead of generic internal error.
Durable Object CPU limit exception message
As of 2021-04-23, when a Durable Object exceeds its CPU time limit, an exception with an explanatory message is thrown to the caller instead of generic internal error.