Local development (5)·续

Note

If you have use-cases for connecting to any of the remote resources above, please open a feature request ↗︎ in our workers-sdk repository ↗︎.

Using remote resources with Durable Objects and Workflows

While Durable Object and Workflow bindings cannot currently be remote, you can still use them during local development and have them interact with remote resources.

There are two recommended patterns for this:

  • Local Durable Objects/Workflows with remote bindings:

When you enable remote bindings in your Wrangler configuration, your locally running Durable Objects and Workflows can access remote resources. This allows such bindings, although run locally, to interact with remote resources during local development. - Accessing remote Durable Objects/Workflows via service bindings:

To interact with remote Durable Object or Workflow instances, deploy a Worker that defines those. Then, in your local Worker, configure a remote service binding pointing to the deployed Worker. Your local Worker will be then able to interact with the remote deployed Worker, which in turn can communicate with the remote Durable Objects/Workflows. Using this method, you can create a communication channel via the remote service binding, effectively using the deployed Worker as a proxy interface to the remote bindings during local development.

Important Considerations

  • Cloudflare Access: If your Worker is protected by Cloudflare Access, Wrangler must authenticate with Access when connecting to remote bindings. Refer to Connect to Access-protected Workers.
  • Data modification: Operations (writes, deletes, updates) on bindings connected remotely will affect your actual data in the targeted Cloudflare resource (be it preview or production).
  • Billing: Interactions with remote Cloudflare services through these connections will incur standard operational costs for those services (such as KV operations, R2 storage/operations, AI requests, D1 usage).
  • Network latency: Expect network latency for operations on these remotely connected bindings, as they involve communication over the internet.

Connect to Access-protected Workers

If your Worker is protected by Cloudflare Access, Wrangler must authenticate with Access when connecting to your remote bindings. This applies whether Access protects the Worker itself, all Workers in the account, a workers.dev hostname, a Custom Domain, or another hostname or path that routes to the Worker.

There are two ways you can authenticate against Access:

  • Interactive login (local development): If you have a policy defined that accepts user login, then Wrangler launches the interactive cloudflared access login flow in your browser. No additional setup is required beyond being signed in to the correct account. If the policy only allows service token authentication, Wrangler will skip the interactive flow and throw an error indicating that service token credentials are required.
  • Service token (CI / non-interactive environments): In CI/CD pipelines and other non-interactive contexts, or where the policy only allows service token authentication, Wrangler cannot trigger the interactive flow via the browser. Authentication must be via a Cloudflare Access service token instead. If you do not configure a service token in a non-interactive environment, Wrangler will throw an error rather than attempting the interactive flow.

To set up service token authentication:

  1. Create a service token.

In the Cloudflare dashboard, go to Zero Trust > Access > Service Auth > Service Tokens and create a new token. Refer to Service tokens for the full reference. You will be shown a Client ID and a Client Secret — save them somewhere safe, as the secret is not shown again. 2. Add a Service Auth policy to the Access application that protects your Worker.

Open the existing Access application that already protects the Worker or the hostname you use for remote bindings, and attach a new policy with: - Action: Service Auth - Include: The service token you created, or "Any Access Service Token" if you want to allow any service token to access the Worker.

Caution

Do not create a separate Access application for the same Worker or hostname only to add service token authentication. Doing so can conflict with the Access application that already protects the Worker. Attach the Service Auth policy to the existing application instead. 3. Expose the credentials to Wrangler.

Set the CLOUDFLARE_ACCESS_CLIENT_ID and CLOUDFLARE_ACCESS_CLIENT_SECRET system environment variables in the environment that runs Wrangler:

   export CLOUDFLARE_ACCESS_CLIENT_ID=<CLIENT_ID>
   export CLOUDFLARE_ACCESS_CLIENT_SECRET=<CLIENT_SECRET>
   ```

In CI, store the values as secrets and expose them as environment variables to the step that runs Wrangler.

### API

Wrangler provides programmatic utilities to help tooling authors support remote binding connections when running Workers code with [Miniflare](https://developers.cloudflare.com/workers/testing/miniflare/).

**Key APIs include:**

- [`startRemoteProxySession`](#startRemoteProxySession): Starts a proxy session that allows interaction with remote bindings.
- [`unstable_convertConfigBindingsToStartWorkerBindings`](#unstable_convertconfigbindingstostartworkerbindings): Utility for converting binding definitions.
- [`experimental_maybeStartOrUpdateProxySession`](#experimental_maybestartorupdatemixedmodesession): Convenience function to easily start or update a proxy session.

#### `startRemoteProxySession`

This function starts a proxy session for a given set of bindings. It accepts options to control session behavior, including an `auth` option with your Cloudflare account ID and API token for remote binding access.

It returns an object with:

- `ready` `Promise<void>`: Resolves when the session is ready.
- `dispose` `() => Promise<void>`: Stops the session.
- `updateBindings` `(bindings: StartDevWorkerInput['bindings']) => Promise<void>`: Updates session bindings.
- `remoteProxyConnectionString` `remoteProxyConnectionString`: String to pass to Miniflare for remote binding access.

#### `unstable_convertConfigBindingsToStartWorkerBindings`

The `unstable_readConfig` utility returns an `Unstable_Config` object which includes the definition of the bindings included in the configuration file. These bindings definitions are however not directly compatible with `startRemoteProxySession`. It can be quite convenient to however read the binding declarations with `unstable_readConfig` and then pass them to `startRemoteProxySession`, so for this wrangler exposes `unstable_convertConfigBindingsToStartWorkerBindings` which is a simple utility to convert the bindings in an `Unstable_Config` object into a structure that can be passed to `startRemoteProxySession`.

Note

This type conversion is temporary. In the future, the types will be unified so you can pass the config object directly to `startRemoteProxySession`.

#### `maybeStartOrUpdateRemoteProxySession`

This wrapper simplifies proxy session management. It takes:

- An object that contains either:
  - the path to a Wrangler configuration and a potential target environment
  - the name of the Worker and the bindings it is using
- The current proxy session details (this parameter can be set to `null` or not being provided if none).
- Potentially the auth data to use for the remote proxy session.

It returns an object with the proxy session details if started or updated, or `null` if no proxy session is needed.

The function:

- Based on the first argument prepares the input arguments for the proxy session.
- If there are no remote bindings to be used (nor a pre-existing proxy session) it returns null, signaling that no proxy session is needed.
- If the details of an existing proxy session have been provided it updates the proxy session accordingly.
- Otherwise if starts a new proxy session.
- Returns the proxy session details (that can later be passed as the second argument to `maybeStartOrUpdateRemoteProxySession`).

#### Example

Here's a basic example of using Miniflare with `maybeStartOrUpdateRemoteProxySession` to provide a local dev session with remote bindings. This example uses a single hardcoded KV binding.

```js
import { Miniflare, MiniflareOptions } from "miniflare";
import { maybeStartOrUpdateRemoteProxySession } from "wrangler";

let mf;

let remoteProxySessionDetails = null;

async function startOrUpdateDevSession() {
    remoteProxySessionDetails = await maybeStartOrUpdateRemoteProxySession(
        {
            bindings: {
                MY_KV: {
                    type: "kv_namespace",
                    id: "kv-id",
                    remote: true,
                },
            },
        },
        remoteProxySessionDetails,
    );

const miniflareOptions = {
        scriptPath: "./worker.js",
        kvNamespaces: {
            MY_KV: {
                id: "kv-id",
                remoteProxyConnectionString:
                    remoteProxySessionDetails?.session.remoteProxyConnectionString,
            },
        },
    };

if (!mf) {
        mf = new Miniflare(miniflareOptions);
    } else {
        mf.setOptions(miniflareOptions);
    }
}

// ... tool logic that invokes `startOrUpdateDevSession()` ...

// ... once the dev session is no longer needed run
// `remoteProxySessionDetails?.session.dispose()`
import { Miniflare, MiniflareOptions } from "miniflare";
import { maybeStartOrUpdateRemoteProxySession } from "wrangler";

let mf: Miniflare | null;

let remoteProxySessionDetails: Awaited<
    ReturnType<typeof maybeStartOrUpdateRemoteProxySession>
> | null = null;

async function startOrUpdateDevSession() {
    remoteProxySessionDetails = await maybeStartOrUpdateRemoteProxySession(
        {
            bindings: {
                MY_KV: {
                    type: "kv_namespace",
                    id: "kv-id",
                    remote: true,
                },
            },
        },
        remoteProxySessionDetails,
    );

const miniflareOptions: MiniflareOptions = {
        scriptPath: "./worker.js",
        kvNamespaces: {
            MY_KV: {
                id: "kv-id",
                remoteProxyConnectionString:
                    remoteProxySessionDetails?.session.remoteProxyConnectionString,
            },
        },
    };

if (!mf) {
        mf = new Miniflare(miniflareOptions);
    } else {
        mf.setOptions(miniflareOptions);
    }
}

// ... tool logic that invokes `startOrUpdateDevSession()` ...

// ... once the dev session is no longer needed run
// `remoteProxySessionDetails?.session.dispose()`

wrangler dev --remote (Legacy)

Separate from Miniflare-powered local development, Wrangler also offers a fully remote development mode via wrangler dev --remote. Remote development is not supported in the Vite plugin.

npmyarnpnpm

npx wrangler dev --remote
yarn wrangler dev --remote
pnpm wrangler dev --remote

During remote development, all of your Worker code is uploaded to a temporary preview environment on Cloudflare's infrastructure, and changes to your code are automatically uploaded as you save.

When using remote development, all bindings automatically connect to their remote resources. Unlike local development, you cannot configure bindings to use local simulations - they will always use the deployed resources on Cloudflare's network.

When to use Remote development

  • For most development tasks, the most efficient and productive experience will be local development along with remote bindings when needed.
  • You may want to use wrangler dev --remote for testing features or behaviors that are highly specific to Cloudflare's network and cannot be adequately simulated locally or tested via remote bindings.

Considerations

  • Iteration is significantly slower than local development due to the upload/deployment step for each change.

Limitations

  • When you run a remote development session using the --remote flag, a limit of 50 routes per zone is enforced. Learn more in Workers platform limits.
  • Python Workers do not support the --remote flag. Use remote bindings instead.

Was this helpful?

YesNo

On this page

Local development (5)·续 - 图1Docs

{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/workers/local-development/#page","headline":"Local development","description":"Develop and test your Workers locally.","url":"https://developers.cloudflare.com/workers/local-development/","inLanguage":"en","image":"https://developers.cloudflare.com/workers/local-development/og.png?v=f54ca19c6e1d7c99","dateModified":"2026-10-22","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}


description: Supported bindings per development mode title: Supported bindings per development mode image: https://developers.cloudflare.com/workers/local-development/bindings-per-env/og.png?v=2340d9abe6ad6ebf


Skip to content

Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/workers/llms.txt
Use this file to discover all available pages before exploring further.