Skip to content

Connect Workers to Cloudflare Mesh

Last updated View as MarkdownAgent setup

This example uses a VPC Network binding with Cloudflare Mesh (formerly WARP Connector) to connect through your account's default virtual network. It does not require pre-registering individual hosts or specifying a Cloudflare Tunnel UUID.

The cf1:network selector uses your account's default virtual network. Your Worker can reach destinations routed through that network, including Mesh nodes, client devices, subnet or hostname routes announced through Cloudflare Tunnel or Cloudflare Mesh, and destinations connected through a Cloudflare WAN on-ramp (GRE, IPsec, or CNI). To select another configured virtual network, refer to VPC Networks configuration.

Prerequisites

  • A Cloudflare Mesh node connected to your private network
  • Private services running behind your Mesh node (for example, an internal API, database, or web application)

1. Configure your Worker

Bind your Worker to Cloudflare Mesh using network_id: "cf1:network" in your Wrangler configuration:

{
	"$schema": "./node_modules/wrangler/config-schema.json",
	"name": "mesh-gateway",
	"main": "src/index.js",
	"upload_source_maps": true,
	// Set this to today's date
	"compatibility_date": "2026-11-06",
	"vpc_networks": [
		{
			"binding": "MESH",
			"network_id": "cf1:network",
			"remote": true
		}
	]
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "mesh-gateway"
main = "src/index.js"
upload_source_maps = true
# Set this to today's date
compatibility_date = "2026-11-06"

[[vpc_networks]]
binding = "MESH"
network_id = "cf1:network"
remote = true

This binding can reach services routed through your account's default virtual network, including services behind Cloudflare Tunnel, Mesh nodes, and Cloudflare WAN on-ramps.

2. Implement the Worker

Use the VPC Network binding to access services by private IP address. Cloudflare Mesh currently supports IP-based routing only.

index.jsjs
// You can target a Mesh node directly by its Mesh IP or any private IP
// on a subnet route behind the node
const SERVICE_IP = "10.0.1.50";
const SERVICE_PORT = 8080;

export default {
	async fetch(request, env, ctx) {
		try {
			const response = await env.MESH.fetch(
				`http://${SERVICE_IP}:${SERVICE_PORT}/api/data`,
			);
			return response;
		} catch (error) {
			// fetch() throws if the VPC Network cannot connect to the target
			return new Response("Service unavailable", { status: 503 });
		}
	},
};

Unlike VPC Services, the URL you pass to fetch() or the address you pass to connect() determines the actual destination. You can reach any IP and port accessible through your Mesh network without creating separate bindings for each service.

TCP connections

You can also use connect() to open raw TCP sockets to non-HTTP services through the same binding:

index.jsjs
// You can target a Mesh node directly by its Mesh IP or any private IP
// on a subnet route behind the node
const REDIS_IP = "10.0.1.50";
const REDIS_PORT = 6379;

export default {
	async fetch(request, env, ctx) {
		try {
			const socket = await env.MESH.connect(`${REDIS_IP}:${REDIS_PORT}`);

			const writer = socket.writable.getWriter();
			await writer.write(new TextEncoder().encode("PING\r\n"));
			await writer.close();

			return new Response(socket.readable);
		} catch (error) {
			// connect() throws if the VPC Network cannot connect to the target
			return new Response("Service unavailable", { status: 503 });
		}
	},
};

3. Deploy and test

Deploy your Worker and verify it can reach your private services:

npx wrangler deploy
# Test accessing the internal user API
curl https://mesh-gateway.workers.dev/api/users

# Test accessing metrics by private IP
curl https://mesh-gateway.workers.dev/api/metrics

Next steps

Was this helpful?