A single dev flow for production data

Remote bindings, now generally available, let you connect local Worker code to deployed resources like R2 buckets and D1 databases. Instead of deploying for every code change, you can iterate locally against real data and services, bridging the gap between a fully local simulation and production infrastructure.

The motivation is straightforward: local development with simulated bindings is excellent for iterating on logic with test data, but it doesn't cover every scenario. Teams may want to share resources across members, reproduce bugs tied to real data, or simply verify that an application will behave correctly against production resources. Previously, the only way to access remote resources while developing was through wrangler dev --remote, which bypassed all the improvements made to the local development experience over recent years.

With Wrangler v4.37.0, that trade-off disappears. You can now choose, on a per-binding basis, whether a binding resolves to a remote resource or a local simulation—simply by adding remote: true to the binding definition in your Wrangler config file. No complex credential management is involved; the connection uses Wrangler's existing OAuth flow with the Cloudflare API.

Some bindings already worked this way. The AI binding, for instance, has always connected to a remote resource because a true local experience would require downloading a massive set of models. But different products needed similar approaches independently, leading to a patchwork of solutions. Remote bindings unify this under a single solution that works across all binding types.

The architecture: borrowing from production

A naive approach to remote bindings would be to replace the local env with stubs that translate every binding operation into a direct Cloudflare API call. For example, a local env.KV.put("key", "value") would become a PUT request to the appropriate KV namespace endpoint.

That works for bindings with mature HTTP APIs, but it comes with significant costs: you'd need to replicate the entire bindings API surface and transform every possible operation into an equivalent HTTP call. Worse, some binding operations have no direct API equivalent and simply can't be supported this way.

The solution turned out to be simpler. Under the hood, most Workers bindings—including KV—are implemented as service bindings between your authored Worker and a platform Worker that implements the service. The Worker runtime translates JS API calls like env.KV.get() into HTTP requests that cross a natural network boundary between the two Workers.

That boundary is the key. Instead of the production runtime translating a binding call into an HTTP request, the local runtime (workerd) can do the same translation and send the request directly to the remote service, bypassing the production runtime entirely.

The result: a locally running Worker with a remote binding connects through a remote proxy client to a remote proxy server, which communicates with the actual production resource. Each binding can independently choose its path—remote proxy client or local simulation—so a single Worker can simultaneously use locally simulated KV and R2 namespaces while connecting to a real remote KV namespace, all with just a flag per binding.

JSRPC and Cap'n Web

HTTP-backed bindings like KV and R2 were only part of the puzzle. Modern bindings, including Images and service bindings to your own Workers, communicate via JSRPC rather than HTTP. Supporting remote access for these required a way for a local workerd instance to speak JSRPC to a production runtime.

A parallel project made this possible. By communicating over WebSockets using Cap'n Web, the connection between the local workerd and the remote runtime instance can carry JSRPC traffic, extending remote bindings to the newer binding types.

Beyond Wrangler: Vite, Vitest, and shared utilities

Remote bindings aren't limited to wrangler dev. Support is also included in the Cloudflare Vite Plugin and @cloudflare/vitest-pool-workers packages. To make this extensible, the Wrangler package now exports utilities like startRemoteProxySession, allowing other tools in the JavaScript ecosystem to implement remote bindings without relying on wrangler dev itself.

To try it out, all you need is Wrangler v4.37.0 (or @cloudflare/vite-plugin v1.13.0, or @cloudflare/vitest-pool-workers v0.9.0). Add remote: true to any binding in your Wrangler config file, and local development can tap into production data without changing a single line of your Worker's code.