Skip to content

Workers Binding API

VPC bindings provide APIs for accessing private services from your Worker. Both VPC Services and VPC Networks expose a fetch() method for HTTP traffic. VPC Networks also expose a connect() method for raw TCP connections. The difference between binding types is in routing scope, not in API surface.

Binding types

VPC Service

A VPC Service binding routes requests to a specific pre-registered host and port. The VPC Service configuration always determines the connection target, even if a different URL or host is present in the fetch() call.

  • The host provided in fetch() does not control routing. It only populates the Host header and, when using https, the Server Name Indication (SNI) value.
  • The port provided in fetch() is ignored — the port specified in the VPC Service configuration is always used.

VPC Network

A VPC Network binding grants access to any service reachable through the bound Cloudflare Tunnel or through Cloudflare Mesh — including subnet and hostname routes announced through Cloudflare Tunnel or Mesh, and destinations connected through Cloudflare WAN on-ramps (GRE, IPsec, or CNI). The URL passed to fetch() or the address passed to connect() determines the actual destination — hostname or IP address and port.

fetch()

Makes an HTTP request to the private service through the bound Cloudflare Tunnel or Cloudflare Mesh. Available on both VPC Service and VPC Network bindings.

JavaScript
const response = await env.MY_BINDING.fetch(resource, options);

Parameters

  • resource (string | URL | Request) — The URL to fetch. Must be an absolute URL including protocol, host, and path (for example, http://internal-api/api/users).
  • options (optional RequestInit) — Standard fetch options including:
    • method — HTTP method (GET, POST, PUT, DELETE, etc.)
    • headers — Request headers
    • body — Request body
    • signal — AbortSignal for request cancellation

Return value

Returns a Promise<Response> that resolves to a standard Fetch API Response object.

Examples

The following examples apply to both VPC Service and VPC Network bindings.

Basic GET request

JavaScript
export default {
async fetch(request, env) {
const privateRequest = new Request(
"http://internal-api.company.local/users",
);
const response = await env.MY_BINDING.fetch(privateRequest);
const users = await response.json();
return new Response(JSON.stringify(users), {
headers: { "Content-Type": "application/json" },
});
},
};

POST request with body

JavaScript
export default {
async fetch(request, env) {
const privateRequest = new Request(
"http://internal-api.company.local/users",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${env.API_TOKEN}`,
},
body: JSON.stringify({
name: "John Doe",
email: "john@example.com",
}),
},
);
const response = await env.MY_BINDING.fetch(privateRequest);
if (!response.ok) {
return new Response("Failed to create user", { status: response.status });
}
const user = await response.json();
return new Response(JSON.stringify(user), {
headers: { "Content-Type": "application/json" },
});
},
};

Request with HTTPS and IP address

JavaScript
export default {
async fetch(request, env) {
const privateRequest = new Request("https://10.0.1.50/api/data");
const response = await env.MY_BINDING.fetch(privateRequest);
return response;
},
};

connect()

Opens a raw TCP connection to a private destination through the bound Cloudflare Tunnel or Cloudflare Mesh. Available on VPC Network bindings only.

JavaScript
const socket = await env.MY_BINDING.connect(address);

Parameters

  • address (string | SocketAddress) — The destination to connect to. Pass a string in "host:port" format (for example, "10.0.1.50:6379") or a SocketAddress object with hostname and port.

Return value

Returns a Promise<Socket> that resolves to a Socket with readable and writable streams. If connect() cannot establish the connection, it throws an exception.

Examples

Connect to a private Redis instance

JavaScript
export default {
async fetch(request, env) {
const socket = await env.MY_BINDING.connect("10.0.1.50:6379");
const writer = socket.writable.getWriter();
await writer.write(new TextEncoder().encode("PING\r\n"));
await writer.close();
return new Response(socket.readable);
},
};

Connect using a SocketAddress object

JavaScript
export default {
async fetch(request, env) {
const socket = await env.MY_BINDING.connect({
hostname: "10.0.1.50",
port: 6379,
});
const writer = socket.writable.getWriter();
await writer.write(new TextEncoder().encode("PING\r\n"));
await writer.close();
return new Response(socket.readable);
},
};

Required roles

To bind a VPC Service or VPC Network in a Worker, your user needs Connectivity Directory Bind (or Connectivity Directory Admin). Binding directly to a Cloudflare Tunnel through a VPC Network binding requires Connectivity Directory Admin. For role definitions, refer to Roles.

Next steps