---
title: Cloudflare Workers VPC
description: Securely connect your private cloud to Cloudflare to build cross-cloud apps.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Workers VPC

Securely connect your private cloud to Cloudflare to build cross-cloud apps.

 Available on Free and Paid plans 

Workers VPC allows you to connect your Workers to your private APIs, services, and databases in external clouds (AWS, Azure, GCP, on-premise, and others) that are not accessible from the public Internet.

With Workers VPC, you can configure a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) to establish secure, private connections from your private networks to Cloudflare. Then, you can configure a [VPC Service](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) for each service in the external private network you need to connect to, and use [VPC Service bindings](https://developers.cloudflare.com/workers-vpc/api/) to connect from Workers. VPC Services support both HTTP and TCP service types, allowing you to connect to web APIs and databases (through [Hyperdrive](https://developers.cloudflare.com/hyperdrive/)).

You can also use [VPC Network bindings](https://developers.cloudflare.com/workers-vpc/configuration/vpc-networks/) to give Workers broader access to your private infrastructure — services behind [Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/), subnet and hostname routes announced through Cloudflare Tunnel or Mesh, and destinations connected through [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) on-ramps (GRE, IPsec, and CNI). The same binding can also egress to public Internet destinations through [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/), so your existing Zero Trust traffic policies and logs apply to Worker requests.

[Worker](https://developers.cloudflare.com/workers/) 

Bind via [vpc\_services](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) or [vpc\_networks](https://developers.cloudflare.com/workers-vpc/configuration/vpc-networks/) 

[Cloudflare Tunnel](https://developers.cloudflare.com/tunnel/) 

Reach private applications or networks through `cloudflared` 

[Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/) 

Reach the full account through `cf1:network` 

[Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) 

Reach destinations through GRE, IPsec, or CNI on-ramps

[Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/) 

Mesh and WAN traffic flows through Gateway, with policies enforced and traffic [logged](https://developers.cloudflare.com/cloudflare-one/insights/logs/dashboard-logs/gateway-logs/).

[ DNS ](https://developers.cloudflare.com/cloudflare-one/traffic-policies/dns-policies/)[ HTTP ](https://developers.cloudflare.com/cloudflare-one/traffic-policies/http-policies/)[ Network ](https://developers.cloudflare.com/cloudflare-one/traffic-policies/network-policies/) 

Private services 

APIs, databases, hosts in your network — reachable via any on-ramp

Public Internet 

Reachable via Mesh or WAN

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

* [ index.ts ](#tab-panel-11180)
* [ wrangler.jsonc ](#tab-panel-11181)

TypeScript

```

export default {

  async fetch(request, env, ctx) {

    // Access your private API through the service binding

    const response = await env.PRIVATE_API.fetch(

      "http://internal-api.company.local/data",

    );


      // Process the response from your private network

      const data = await response.json();


      return new Response(JSON.stringify(data), {

        headers: { "content-type": "application/json" },

      });

    },


};


```

```

  {

    "$schema": "node_modules/wrangler/config-schema.json",

    "name": "WORKER-NAME",

    "main": "src/index.ts",

    "compatibility_date": "2025-02-04",

    "vpc_services": [

      {

        "binding": "PRIVATE_API",

        "service_id": "ENTER_SERVICE_ID",

        "remote": true

      }

    ]

  }


```

## Use cases

### Access private APIs from Workers applications

Deploy APIs or full-stack applications to Workers that connect to private authentication services, CMS systems, internals APIs, and more. Your Workers applications run globally with optimized access to the backend services of your private network.

### API gateway

Route requests to internal microservices in your private network based on URL paths. Centralize access control and load balancing for multiple private services on Workers.

### Internal tooling, agents, dashboards

Build employee-facing applications and MCP servers that aggregate data from multiple private services. Create unified dashboards, admin panels, and internal tools without exposing backend systems.

### Apply Zero Trust controls to Worker egress

Route public Internet traffic from your Workers through [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/) so existing DNS, HTTP, Network, and egress policies — and the corresponding logs — apply to programmatic compute the same way they apply to your workforce. Stop a Worker from reaching unwanted destinations without writing custom proxy logic.

## Related products

**[Workers](https://developers.cloudflare.com/workers/)** 

Build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale.

**[Hyperdrive](https://developers.cloudflare.com/hyperdrive/)** 

Connect to PostgreSQL and MySQL databases from Workers with connection pooling and caching built-in, available to all Workers plans.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}}]}
```

---

---
title: Get started
description: Create your first Workers VPC Service and connect a Worker to your private network.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

This guide will walk you through creating your first Workers VPC Service, allowing your Worker to access resources in your private network.

You will create a Workers application, create a Tunnel in your private network to connect it to Cloudflare, and then configure VPC Services for the services on your private network you want to access from Workers.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

## Prerequisites

Before you begin, ensure you have completed the following:

1. Sign up for a [Cloudflare account ↗](https://dash.cloudflare.com/sign-up/workers-and-pages).
2. Install [Node.js ↗](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).

Node.js version manager

Use a Node version manager like [Volta ↗](https://volta.sh/) or [nvm ↗](https://github.com/nvm-sh/nvm) to avoid permission issues and change Node.js versions. [Wrangler](https://developers.cloudflare.com/workers/wrangler/install-and-update/), discussed later in this guide, requires a Node version of `16.17.0` or later.

Additionally, you will need:

* Access to a private network (your local network, AWS VPC, Azure VNet, GCP VPC, or on-premise networks)
* The **Connectivity Directory Bind** role to bind to existing VPC Services from Workers.
* Or, the **Connectivity Directory Admin** role to create VPC Services, and bind to them from Workers.

## 1\. Create a new Worker project

Create a new Worker project using Wrangler:

 npm  yarn  pnpm 

```
npm create cloudflare@latest -- workers-vpc-app
```

```
yarn create cloudflare workers-vpc-app
```

```
pnpm create cloudflare@latest workers-vpc-app
```

For setup, select the following options:

* For _What would you like to start with?_, choose `Hello World example`.
* For _Which template would you like to use?_, choose `Worker only`.
* For _Which language do you want to use?_, choose `TypeScript`.
* For _Do you want to use git for version control?_, choose `Yes`.
* For _Do you want to deploy your application?_, choose `No` (we will be making some changes before deploying).

Navigate to your project directory:

Terminal window

```

cd workers-vpc-app


```

## 2\. Set up Cloudflare Tunnel

A Cloudflare Tunnel creates a secure connection from your private network to Cloudflare. This tunnel will allow Workers to securely access your private resources. You can create the tunnel on a virtual machine or container in your external cloud, or even on your local desktop for the sake of this tutorial.

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels) and select the **Tunnels** tab.
2. Select **Create** to create a new tunnel.
3. Enter a name for your tunnel (for example, `workers-vpc-tunnel`) and select **Save tunnel**.
4. Choose your operating system and architecture. The dashboard will provide specific installation instructions for your environment.
5. Follow the provided commands to download and install `cloudflared`, and execute the service installation command with your unique token.

The dashboard will confirm when your tunnel is successfully connected.

### Configuring your private network for Cloudflare Tunnel

Once your tunnel is connected, you will need to ensure it can access the services that you want your Workers to have access to. The tunnel should be installed on a machine that can reach the internal resources you want to expose to Workers VPC. In external clouds, this may mean configuring Access-Control-Lists, Security Groups, or VPC Firewall Rules to ensure that the tunnel can access the desired services.

Note

This guide provides a quick setup for Workers VPC.

For comprehensive tunnel configuration, monitoring, and management, refer to the [full Cloudflare Tunnel documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/).

## 3\. Create a VPC Service

Now that your tunnel is running, create a VPC Service that Workers can use to access your internal resources:

* [ Dashboard ](#tab-panel-11204)
* [ Wrangler CLI ](#tab-panel-11205)

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc) and select the **VPC Services** tab.
2. Select **Create** to create a new VPC Service.
3. Enter a **Service name** for your VPC Service (for example, `my-private-api`).
4. Select your tunnel from the **Tunnel** dropdown, or select **Create Tunnel** if you need to create a new one.
5. Enter the **Host or IP address** of your internal service (for example, `localhost`, `internal-api.company.local`, or `10.0.1.50`).
6. Configure **Ports**. Select either:  
   * **Use default ports** for standard HTTP (80) and HTTPS (443)  
   * **Provide port values** to specify custom HTTP and HTTPS ports
7. Configure **DNS Resolver**. Select either:  
   * **Use tunnel as resolver** to use the tunnel's built-in DNS resolution  
   * **Custom resolver** and enter your DNS resolver IP (for example, `8.8.8.8`)
8. Select **Create service** to create your VPC Service.

The dashboard will display your new VPC Service with a unique Service ID. Save this Service ID for the next step.

For an HTTP service:

Terminal window

```

npx wrangler vpc service create my-private-api \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname <YOUR_HOSTNAME>


```

For a TCP service (for example, a PostgreSQL database):

Terminal window

```

npx wrangler vpc service create my-database \

  --type tcp \

  --tcp-port 5432 \

  --app-protocol postgresql \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --ipv4 <YOUR_IPV4_ADDRESS>


```

Replace:

* `<YOUR_TUNNEL_ID>` with your tunnel ID from step 2
* `<YOUR_HOSTNAME>` with your internal service hostname (for example, `internal-api.company.local`)
* `<YOUR_IPV4_ADDRESS>` with the private IP address of your service (for example, `10.0.1.50`)

You can also:

* Create services using IP addresses by replacing `--hostname <YOUR_HOSTNAME>` with `--ipv4 <YOUR_IPV4_ADDRESS>`, `--ipv6 <YOUR_IPV6_ADDRESS>`, or both for dual-stack configuration
* Specify custom ports for HTTP services by adding `--http-port <PORT>` and/or `--https-port <PORT>` (for example, `--http-port 8080 --https-port 8443`)
* Set the TLS certificate verification mode with `--cert-verification-mode` (`verify_full`, `verify_ca`, or `disabled`)

The command will return a service ID. Save this for the next step.

If you encounter permission errors, refer to [Required roles](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#required-roles).

## 4\. Configure your Worker

Add the VPC Service binding to your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-11206)
* [  wrangler.toml ](#tab-panel-11207)

JSONC

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "workers-vpc-app",

  "main": "src/index.ts",

  // Set this to today's date

  "compatibility_date": "2026-06-12",

  "vpc_services": [

    {

      "binding": "VPC_SERVICE",

      "service_id": "<YOUR_SERVICE_ID>"

    }

  ]

}


```

TOML

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "workers-vpc-app"

main = "src/index.ts"

# Set this to today's date

compatibility_date = "2026-06-12"


[[vpc_services]]

binding = "VPC_SERVICE"

service_id = "<YOUR_SERVICE_ID>"


```

Replace `<YOUR_SERVICE_ID>` with the service ID from step 3.

## 5\. Write your Worker code

Update your Worker to use the VPC Service binding. The following example:

TypeScript

```

export default {

  async fetch(request, env, ctx): Promise<Response> {

    const url = new URL(request.url);


    // This is a simple proxy scenario.

    // In this case, you will need to replace the URL with the proper protocol (http vs. https), hostname and port of the service.

    // For example, this could be "http://localhost:1111", "http://192.0.0.1:3000", "https://my-internal-api.example.com"

    const targetUrl = new URL(

      `http://<ENTER_SERVICE_HOST>:<ENTER_SERVICE_PORT>${url.pathname}${url.search}`,

    );


    // Create new request with the target URL but preserve all other properties

    const proxyRequest = new Request(targetUrl, {

      method: request.method,

      headers: request.headers,

      body: request.body,

    });


    const response = await env.VPC_SERVICE.fetch(proxyRequest);


    return response;

  },

} satisfies ExportedHandler<Env>;


```

## 6\. Test locally

Test your Worker locally. You must use remote VPC Services, using either [Workers remote bindings](https://developers.cloudflare.com/workers/development-testing/#remote-bindings) as was configured in your `wrangler.jsonc` configuration file, or using `npx wrangler dev --remote`:

Terminal window

```

npx wrangler dev


```

Visit `http://localhost:8787` to test your Worker's connection to your private network.

## 7\. Deploy your Worker

Once testing is complete, deploy your Worker:

Terminal window

```

npx wrangler deploy


```

Your Worker is now deployed and can access your private network resources securely through the Cloudflare Tunnel. If you encounter permission errors, refer to [Required roles](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#required-roles).

## Next steps

* Explore [configuration options](https://developers.cloudflare.com/workers-vpc/configuration/) for advanced setups
* Set up [high availability tunnels](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/hardware-requirements/) for production
* View [platform-specific guides](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/) for AWS, Azure, GCP, and Kubernetes
* Check out [examples](https://developers.cloudflare.com/workers-vpc/examples/) for common use cases

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/get-started/","name":"Get started"}}]}
```

---

---
title: Workers Binding API
description: API reference for VPC Service and VPC Network bindings in Workers.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Workers Binding API

VPC bindings provide a `fetch()` API for accessing private services from your Worker through Cloudflare Tunnel. Both [VPC Services](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) and [VPC Networks](https://developers.cloudflare.com/workers-vpc/configuration/vpc-networks/) expose the same `fetch()` method — the difference is in routing scope.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

## Binding types

### VPC Service

A VPC Service binding routes requests to a specific pre-registered host and port. The [VPC Service configuration](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#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()` 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.

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

Absolute URLs required

VPC binding fetch requests must use absolute URLs including the protocol (`http`/`https`), host, and path. Relative paths are not supported.

### Return value

Returns a `Promise<Response>` that resolves to a [standard Fetch API Response object ↗](https://developer.mozilla.org/en-US/docs/Web/API/Response).

### 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;

  },

};


```

## 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](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles).

## Next steps

* Configure [VPC Services](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/)
* Configure [VPC Networks](https://developers.cloudflare.com/workers-vpc/configuration/vpc-networks/)
* Refer to [usage examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/api/","name":"Workers Binding API"}}]}
```

---

---
title: Cloudflare Tunnel
description: Set up Cloudflare Tunnel to connect your private network to Workers VPC.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare Tunnel

Cloudflare Tunnel creates secure connections from your infrastructure to Cloudflare's global network, providing the network connectivity that allows Workers to access your private resources.

When you create a VPC Service, you specify a tunnel ID and target service. Workers VPC then routes requests from your Worker to the specified tunnel, which establishes a connection to the specified hostname or IP address, such that the target service receives the request and returns a response back to your Worker.

To allow members to create VPC Services that represent a target service reachable via a tunnel, you must assign them the **Connectivity Directory Admin** role. Members with the **Connectivity Directory Bind** role can bind to existing VPC Services from Workers. Binding directly to a tunnel through a VPC Network binding requires the **Connectivity Directory Admin** role.

The tunnel maintains persistent connections to Cloudflare, eliminating the need for inbound firewall rules or public IP addresses.

Note

This section provides tunnel configuration specific to Workers VPC use cases. For comprehensive tunnel documentation including monitoring and advanced configurations, refer to the [full Cloudflare Tunnel documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/).

## Create and run tunnel (`cloudflared`)

Cloudflare Tunnel requires the installation of a lightweight and highly scalable server-side daemon, `cloudflared`, to connect your infrastructure to Cloudflare.

Version and Configuration

Ensure you are running `cloudflared` version 2025.7.0 or later (latest version recommended) to ensure proper DNS resolution and connectivity. Older versions are not supported.

Workers VPC also requires Cloudflare Tunnel to connect using the [QUIC transport protocol](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/run-parameters/#protocol) using `auto` or `quic`. Ensure outbound UDP traffic on port 7844 is allowed through your firewall for QUIC connections.

Cloudflare Tunnels can be created one of two ways:

1. **Remotely-managed tunnels (recommended):** Remotely-managed configurations are stored on Cloudflare, allowing you to manage the tunnel from any machine using the dashboard, API, or Terraform.
2. **Locally-managed tunnels:** A locally-managed tunnel is created by running `cloudflared tunnel create <NAME>` on the command line. Tunnel configuration is stored in your local cloudflared directory.

For Workers VPC, we recommend creating a remotely-managed tunnel through the dashboard. Follow the [Tunnels for Workers VPC dashboard setup guide](https://developers.cloudflare.com/workers-vpc/get-started/) to create your tunnel with provided installation commands shown in the dashboard.

For locally-managed tunnels, refer to the [cloudflared locally-managed tunnels](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/) guide. For manual installation, refer to the [cloudflared downloads page](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/) for platform-specific installation instructions.

Note

Cloudflare Tunnels can either be configured for usage with [Cloudflare Zero Trust](https://developers.cloudflare.com/cloudflare-one/) or [Workers VPC](https://developers.cloudflare.com/workers-vpc/).

Use Tunnels with Zero Trust when you are exposing internal applications securely to your employees with Cloudflare Access and hostnames.

Use Tunnels with Workers VPC when you want to access private APIs, private databases, internal services or other HTTP services within your cloud or on-premise private network from Workers.

The same `cloudflared` instance can be used to cover both Zero Trust and Workers VPC use cases simultaneously.

Note

[Ingress configurations](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/configuration-file/) for locally-managed tunnels are only relevant when using tunnels to expose services to the public internet, and are not required for Workers VPC as routing is handled by the VPC Service configuration.

## Cloud platform setup guides

For platform-specific tunnel deployment instructions for production workloads:

* [AWS](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/aws/) \- Deploy tunnels in Amazon Web Services
* [Azure](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/azure/) \- Deploy tunnels in Microsoft Azure
* [Google Cloud](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/google-cloud-platform/) \- Deploy tunnels in Google Cloud Platform
* [Kubernetes](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/kubernetes/) \- Deploy tunnels in Kubernetes clusters
* [Terraform](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/deployment-guides/terraform/) \- Deploy tunnels using Infrastructure as Code

Refer to the full Cloudflare Tunnel documentation on [how to setup Tunnels for high availability and failover with replicas](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/).

Note

We do not recommend using `cloudflared` in autoscaling setups because downscaling (removing replicas) will break existing user connections to that replica. Additionally, `cloudflared` does not load balance across replicas; replicas are strictly for high availability and requests are routed to the nearest replica.

## Next steps

* Configure [VPC Services](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) to connect your tunnels to Workers
* Review [hardware requirements](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/hardware-requirements/) for capacity planning
* Review the [complete Cloudflare Tunnel documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) for advanced features

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/tunnel/","name":"Cloudflare Tunnel"}}]}
```

---

---
title: Hardware requirements
description: Recommended CPU, memory, and scaling guidelines for cloudflared tunnel hosts.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Hardware requirements

## Recommendations

For production use cases, we recommend the following baseline configuration:

* Run a cloudflared replica on two dedicated host machines per network location. Using two hosts enables server-side redundancy. See [tunnel availability and replicas](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/) for setup instructions.
* Size each host with minimum 4GB of RAM and 4 CPU cores.

This setup is usually sufficient to handle traffic from small-medium sized applications. The actual amount of resources used by cloudflared will depend on many variables, including the number of requests per second, bandwidth, network path, and hardware. If usage increases beyond your existing tunnel capacity, you can scale your tunnel by increasing the hardware allocated to the cloudflared hosts.

## Capacity calculator

To estimate tunnel capacity requirements for your deployment, refer to the [tunnel capacity calculator in the Zero Trust documentation](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-availability/system-requirements/).

## Scaling considerations

Monitor tunnel performance and scale accordingly:

* **CPU utilization**: Keep below 70% average usage
* **Memory usage**: Maintain headroom for traffic spikes
* **Network bandwidth**: Ensure adequate throughput for peak loads
* **Connection count**: Scale cloudflared vertically when approaching capacity limits

## Next steps

* Configure [tunnel deployment](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/)
* Set up [high availability](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/) with multiple replicas

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/tunnel/","name":"Cloudflare Tunnel"}},{"@type":"ListItem","position":5,"item":{"@id":"/workers-vpc/configuration/tunnel/hardware-requirements/","name":"Hardware requirements"}}]}
```

---

---
title: VPC Networks
description: Bind Workers to an entire Cloudflare Tunnel or Cloudflare Mesh without pre-registering hosts.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# VPC Networks

VPC Networks allow your Workers to access any service in your private network without pre-registering individual hosts or ports. You can bind to a specific [Cloudflare Tunnel](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/) to reach any service behind that tunnel, or bind to [Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/) to reach any Mesh node, client device, subnet route or hostname route announced through Cloudflare Tunnel or Mesh, or destination reachable through a [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) on-ramp (GRE, IPsec, or CNI).

At runtime, the URL you pass to `fetch()` determines the destination — any hostname or IP address reachable through the bound Cloudflare Tunnel or through Cloudflare Mesh. This differs from [VPC Services](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/), which require you to create a separate binding for each target host and port combination.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

## Bind to a Cloudflare Tunnel

Note

Binding directly to a Cloudflare Tunnel through a VPC Network binding requires the **Connectivity Directory Admin** role.

Reference a specific Cloudflare Tunnel directly by its UUID:

* [  wrangler.jsonc ](#tab-panel-11182)
* [  wrangler.toml ](#tab-panel-11183)

JSONC

```

{

  "vpc_networks": [

    {

      "binding": "MY_VPC",

      "tunnel_id": "550e8400-e29b-41d4-a716-446655440000",

      "remote": true

    }

  ]

}


```

TOML

```

[[vpc_networks]]

binding = "MY_VPC"

tunnel_id = "550e8400-e29b-41d4-a716-446655440000"

remote = true


```

The `remote` flag must be set to `true` to enable remote bindings during local development.

## Bind to Cloudflare Mesh

[Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/) (formerly WARP Connector) connects your services, devices, and Workers through Cloudflare's global network. When you bind a Worker to Cloudflare Mesh using `network_id: "cf1:network"`, your Worker can reach:

* Any Mesh node or client device in your account
* Subnet routes and hostname routes announced through Cloudflare Tunnel or Cloudflare Mesh
* Destinations reachable through [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) on-ramps (GRE, IPsec, and CNI)
* Public Internet destinations through [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/) — with your existing Zero Trust traffic policies enforced and traffic logged in DNS, HTTP, and Network logs

All of this without specifying a particular Cloudflare Tunnel UUID.

Use `cf1:network` when:

* Your Workers need to reach private services across multiple Cloudflare Tunnels, Mesh nodes, or Cloudflare WAN on-ramps
* You want to access your entire private network from a Worker without managing individual Cloudflare Tunnel bindings
* Your private network topology may change (new connections, new nodes, new routes) and you do not want to update Worker configuration each time
* You want Worker egress to public destinations to flow through Cloudflare Gateway for policy enforcement and visibility

Note

Your account must have at least one active [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/), [Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/) node, or [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) on-ramp that can reach the target services.

For destinations behind Cloudflare WAN on-ramps (GRE, IPsec, or CNI), your network must also route the [Cloudflare source IP range](https://developers.cloudflare.com/cloudflare-wan/configuration/how-to/configure-cloudflare-source-ips/) (`100.64.0.0/12` by default) back through the on-ramp so reply traffic returns to Cloudflare. This is part of standard Cloudflare WAN onboarding. If you have already configured this for Gateway, Load Balancing, or other Cloudflare services that reach your private network through Cloudflare WAN, no additional setup is required.

Bind to Cloudflare Mesh using `network_id: "cf1:network"`:

* [  wrangler.jsonc ](#tab-panel-11184)
* [  wrangler.toml ](#tab-panel-11185)

JSONC

```

{

  "vpc_networks": [

    {

      "binding": "MY_VPC",

      "network_id": "cf1:network",

      "remote": true

    }

  ]

}


```

TOML

```

[[vpc_networks]]

binding = "MY_VPC"

network_id = "cf1:network"

remote = true


```

## Runtime usage

Access any service in your network at runtime:

TypeScript

```

export default {

  async fetch(request: Request, env: Env) {

    // Access a service by private IP

    const response = await env.MY_VPC.fetch("http://10.0.1.50/data");


    // Access another service on a different port

    const dbResponse = await env.MY_VPC.fetch("http://10.0.5.42:5432");


    return response;

  },

};


```

When a VPC Network cannot establish a connection to your target service, `fetch()` throws an exception.

## VPC Networks vs VPC Services

VPC Networks and [VPC Services](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) both connect Workers to private infrastructure, but they make different trade-offs.

* **Use VPC Services** when you have a known set of targets and want each binding scoped to a specific host and port.
* **Use VPC Networks** when you need broader access — an entire Cloudflare Tunnel or all of Cloudflare Mesh — and want the URL in your `fetch()` call to control routing at runtime.

The following table summarizes the differences:

| Feature              | VPC Networks                                                                  | VPC Services              |
| -------------------- | ----------------------------------------------------------------------------- | ------------------------- |
| Scope                | A single Cloudflare Tunnel, or Cloudflare Mesh and Cloudflare WAN routes      | Specific host + port      |
| Configuration        | tunnel\_id (single Cloudflare Tunnel) or cf1:network (account-wide)           | service\_id               |
| Service registration | Not required                                                                  | Required for each target  |
| Use when             | Dynamic discovery, network-wide access, reaching services across your account | Fixed, cataloged services |

## Next steps

* Set up [Cloudflare Tunnel](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/)
* [Set up Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/get-started/)
* [Set up Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/get-started/)
* Try the [Connect Workers to Cloudflare Mesh](https://developers.cloudflare.com/workers-vpc/examples/connect-to-cloudflare-mesh/) example
* Learn about the [Workers Binding API](https://developers.cloudflare.com/workers-vpc/api/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/vpc-networks/","name":"VPC Networks"}}]}
```

---

---
title: VPC Services
description: Register private network resources as VPC Services that Workers can access through Cloudflare Tunnel.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# VPC Services

VPC Services are the core building block of Workers VPC. They represent specific resources in your private network that Workers can access through Cloudflare Tunnel.

You can use bindings to connect to VPC Services from Workers. Every request made to a VPC Service using its `fetch` function will be securely routed to the configured service in the private network.

VPC Services enforce that requests are routed to their intended service without exposing the entire network, securing your workloads and preventing server-side request forgery (SSRF).

Members with the **Connectivity Directory Bind** role can bind to existing VPC Services from Workers. Creating VPC Services requires the **Connectivity Directory Admin** role.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

## VPC Service configuration

A VPC Service consists of:

* **Type**: `http` for HTTP/HTTPS services, or `tcp` for TCP services (for example, PostgreSQL, MySQL)
* **Tunnel ID**: The Cloudflare Tunnel that provides network connectivity
* **Hostname or IPv4/IPv6 addresses**: The hostname, or IPv4 and/or IPv6 addresses to use to route to your service from the tunnel in your private network
* **Ports**: For `http` type, HTTP and/or HTTPS port configuration (optional, defaults to 80/443). For `tcp` type, a TCP port (required).
* **Application protocol** (TCP only): Optionally, specify `postgresql` or `mysql` to indicate the application-layer protocol for the TCP service
* **TLS certificate verification mode**: Optionally, configure how the connection to the origin verifies TLS certificates
* **Resolver IPs**: Optionally, a specific resolver IP can be provided — when not provided, `cloudflared` will direct DNS traffic to the currently configured default system resolver.

### HTTP services

HTTP VPC Services allow Workers to make `fetch()` requests to private HTTP/HTTPS endpoints.

Requests are encrypted in flight until they reach your network via a tunnel, regardless of the scheme used in the URL provided to `fetch`. If the `http` scheme is used, a plaintext connection is established to the service from the tunnel.

The `https` scheme can be used for an encrypted connection within your network, between the tunnel and your service. When the `https` scheme is specified, a hostname provided to the `fetch()` operation is utilized as the Server Name Indication (SNI) value.

VPC Services default to allowing both `http` and `https` schemes to be used. You can provide values for only one of `http_port` or `https_port` to enforce the use of a particular scheme.

When Workers VPC is unable to establish a connection to your service, `fetch()` will throw an exception.

### TCP services

TCP VPC Services allow connections to TCP-based services such as PostgreSQL and MySQL databases. Use the `tcp` service type with a `--tcp-port` to expose a TCP service.

You can optionally specify an `--app-protocol` of `postgresql` or `mysql` to indicate the application-layer protocol. This metadata is used by other Cloudflare products, such as [Hyperdrive](https://developers.cloudflare.com/hyperdrive/), to locate TCP services using a supported wire protocol.

TCP VPC Services are used with [Hyperdrive](https://developers.cloudflare.com/hyperdrive/) to connect Workers to private databases. Refer to [Connect to a private database using Workers VPC](https://developers.cloudflare.com/hyperdrive/configuration/connect-to-private-database-vpc/) for a complete guide.

Note

The [VPC Service configuration](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#vpc-service-configuration) host and port(s) will always be used to connect and route requests to your services, even if a different host or port is present in the URL provided to the `fetch()` operation in the Worker code.

The host provided in the `fetch()` operation is not used to route requests, and instead only populates the `Host` field for a HTTP request, or `Host` and the Server Name Indication (SNI) value presented to your service for a HTTPS request.

The port provided in the `fetch()` operation is ignored — the port specified in the VPC Service configuration for the provided scheme will be used.

### Supported TLS certificates

When using the `https` scheme, the tunnel verifies the TLS certificate presented by your origin service. Workers VPC trusts the following certificate types:

* **Publicly trusted certificates** — Certificates issued by well-known public certificate authorities (for example, Let's Encrypt, DigiCert).
* **[Cloudflare Origin CA certificates](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/)** — Free certificates issued by Cloudflare that encrypt traffic between Cloudflare and your origin. Origin CA certificates are not trusted by browsers, but are trusted by Workers VPC when connecting to your private services.

If your origin service presents a certificate that is not issued by a publicly trusted CA or by Cloudflare Origin CA, the TLS handshake will fail and `fetch()` will throw an exception.

### TLS certificate verification mode

You can configure how the connection to your origin service verifies TLS certificates by setting the `--cert-verification-mode` option when creating or updating a VPC Service. This applies to both HTTP and TCP service types.

| Mode         | Description                                                   |
| ------------ | ------------------------------------------------------------- |
| verify\_full | Verify the full certificate chain and hostname (default)      |
| verify\_ca   | Verify the certificate chain only, skip hostname verification |
| disabled     | Do not verify the server certificate                          |

## Configuration examples

These configurations represent the expected contract of the [REST API for creating a VPC Service](https://developers.cloudflare.com/api/resources/connectivity/subresources/directory/subresources/services/), a type of service within the broader connectivity directory.

### HTTP service with IP addresses

The following is an example of an HTTP VPC Service using custom HTTP and HTTPS ports, and both IPv4 and IPv6 addresses.

JSONC

```

{

  "type": "http",

  "name": "human-readable-name",


  // Port configuration (optional - defaults to 80/443)

  "http_port": 80,

  "https_port": 443,


  // Host configuration

  "host": {

    "ipv4": "10.0.0.1",

    "ipv6": "fe80::",

    "network": {

      "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",

    },

  },

}


```

### HTTP service with hostname

The following is an example of an HTTP VPC Service using a hostname. When using a hostname, provide a `resolver_network` that optionally includes `resolver_ips`.

JSONC

```

{

  "type": "http",

  "name": "human-readable-name",


  // Port configuration (optional - defaults to 80/443)

  "http_port": 80,

  "https_port": 443,


  // Hostname Host (with DNS resolver)

  "host": {

    "hostname": "example.com",

    "resolver_network": {

      "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",

      "resolver_ips": ["10.0.0.1"], // Optional

    },

  },

}


```

### TCP service (for example, PostgreSQL)

The following is an example of a TCP VPC Service for a PostgreSQL database.

JSONC

```

{

  "type": "tcp",

  "name": "my-postgres-db",

  "tcp_port": 5432,

  "app_protocol": "postgresql", // Optional: "postgresql" or "mysql"


  "host": {

    "ipv4": "10.0.0.5",

    "network": {

      "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",

    },

  },

}


```

### Service with TLS certificate verification

The following example creates a TCP service with `verify_ca` certificate verification mode.

JSONC

```

{

  "type": "tcp",

  "name": "my-postgres-db",

  "tcp_port": 5432,

  "app_protocol": "postgresql",


  "host": {

    "ipv4": "10.0.0.5",

    "network": {

      "tunnel_id": "0191dce4-9ab4-7fce-b660-8e5dec5172da",

    },

  },


  "tls_settings": {

    "cert_verification_mode": "verify_ca",

  },

}


```

## Workers binding configuration

Once you have created a VPC Service, you can bind it to your Worker:

* [  wrangler.jsonc ](#tab-panel-11186)
* [  wrangler.toml ](#tab-panel-11187)

JSONC

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "my-worker",

  "main": "src/index.js",

  "vpc_services": [

    {

      "binding": "PRIVATE_API",

      "service_id": "e6a0817c-79c5-40ca-9776-a1c019defe70",

      "remote": true // When true, utilizes [remote bindings](/workers/development-testing/#remote-bindings) to allow access to the VPC Service during local development.

    }

  ]

}


```

TOML

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "my-worker"

main = "src/index.js"


[[vpc_services]]

binding = "PRIVATE_API"

service_id = "e6a0817c-79c5-40ca-9776-a1c019defe70"

remote = true


```

You can have multiple VPC service bindings:

* [  wrangler.jsonc ](#tab-panel-11188)
* [  wrangler.toml ](#tab-panel-11189)

JSONC

```

{

  "vpc_services": [

    {

      "binding": "PRIVATE_API",

      "service_id": "daf43e8c-a81a-4242-9912-4a2ebe4fdd79",

      "remote": true

    },

    {

      "binding": "PRIVATE_DATABASE",

      "service_id": "453b6067-1327-420d-89b3-2b6ad16e6551",

      "remote": true

    },

    {

      "binding": "INTERNAL_CACHE",

      "service_id": "6c39b574-237e-49f4-852a-cea5a93ed8f9",

      "remote": true

    }

  ]

}


```

TOML

```

[[vpc_services]]

binding = "PRIVATE_API"

service_id = "daf43e8c-a81a-4242-9912-4a2ebe4fdd79"

remote = true


[[vpc_services]]

binding = "PRIVATE_DATABASE"

service_id = "453b6067-1327-420d-89b3-2b6ad16e6551"

remote = true


[[vpc_services]]

binding = "INTERNAL_CACHE"

service_id = "6c39b574-237e-49f4-852a-cea5a93ed8f9"

remote = true


```

## Required roles

Workers VPC uses the following account roles:

* `Connectivity Directory Read` to view Workers VPC Services and Tunnels.
* `Connectivity Directory Bind` to list, read, and bind VPC Services in Workers.
* `Connectivity Directory Admin` to create, update, and delete VPC Services, and bind directly to tunnels through a VPC Network binding.

For role definitions, refer to [Roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles).

If your roles were recently updated and commands are still failing, refresh Wrangler authentication:

Terminal window

```

npx wrangler logout

npx wrangler login


```

If you authenticate with an API token (`CLOUDFLARE_API_TOKEN`), ensure the token belongs to a user with the required roles.

## Next steps

* [Configure VPC Services with Terraform](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/terraform/) for managing VPC Services as infrastructure
* Set up [Cloudflare Tunnel](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/) for your environment
* Learn about the [Service Binding API](https://developers.cloudflare.com/workers-vpc/api/)
* Refer to [examples](https://developers.cloudflare.com/workers-vpc/examples/) of common use cases

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/vpc-services/","name":"VPC Services"}}]}
```

---

---
title: Configure with Terraform
description: Learn how to manage VPC Services using the Cloudflare Terraform provider.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configure with Terraform

VPC Services can be managed as infrastructure using the [cloudflare\_connectivity\_directory\_service ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/connectivity%5Fdirectory%5Fservice) resource in the [Cloudflare Terraform provider](https://developers.cloudflare.com/terraform/).

This maps directly to the [connectivity directory](https://developers.cloudflare.com/api/resources/connectivity/subresources/directory/subresources/services/) — the underlying API that the dashboard and Wrangler CLI also use to create and manage VPC Services. The same [VPC Service configuration fields](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#vpc-service-configuration) (type, host, ports, tunnel ID) apply regardless of how the service is created.

Note

Requires Cloudflare Terraform provider v5.13.0 or later.

## VPC Service resource

The `cloudflare_connectivity_directory_service` resource creates a VPC Service in the connectivity directory. Each resource corresponds to one VPC Service entry that a Worker can bind to.

### Hostname-based configuration

When using a hostname, provide `host.hostname` with a `resolver_network` block. This parallels the hostname-based [JSON configuration example](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#configuration-examples).

```

resource "cloudflare_connectivity_directory_service" "my_private_api" {

  account_id = var.account_id

  name       = "my-private-api"

  type       = "http"

  http_port  = 80

  https_port = 443


  host = {

    hostname = "internal-api.example.com"

    resolver_network = {

      tunnel_id = var.tunnel_id

    }

  }

}


```

To use a custom DNS resolver within your private network, add `resolver_ips`:

```

resource "cloudflare_connectivity_directory_service" "my_private_api" {

  account_id = var.account_id

  name       = "my-private-api"

  type       = "http"


  host = {

    hostname = "internal-api.example.com"

    resolver_network = {

      tunnel_id    = var.tunnel_id

      resolver_ips = ["10.0.0.53"]

    }

  }

}


```

### IP-based configuration

When using IP addresses, provide `host.ipv4` and/or `host.ipv6` with a `network` block. This parallels the IP-based [JSON configuration example](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#configuration-examples).

```

resource "cloudflare_connectivity_directory_service" "my_private_api" {

  account_id = var.account_id

  name       = "my-private-api"

  type       = "http"

  http_port  = 8080

  https_port = 8443


  host = {

    ipv4 = "10.0.1.50"

    ipv6 = "fe80::1"

    network = {

      tunnel_id = var.tunnel_id

    }

  }

}


```

### TCP service configuration

For TCP services (for example, databases), set `type = "tcp"` and provide a `tcp_port`. You can optionally specify an `app_protocol` of `postgresql` or `mysql`.

```

resource "cloudflare_connectivity_directory_service" "my_database" {

  account_id   = var.account_id

  name         = "my-postgres-db"

  type         = "tcp"

  tcp_port     = 5432

  app_protocol = "postgresql"


  host = {

    ipv4 = "10.0.0.5"

    network = {

      tunnel_id = var.tunnel_id

    }

  }

}


```

### TLS certificate verification

To configure the TLS certificate verification mode for the connection to the origin, add a `tls_settings` block:

```

resource "cloudflare_connectivity_directory_service" "my_database" {

  account_id   = var.account_id

  name         = "my-postgres-db"

  type         = "tcp"

  tcp_port     = 5432

  app_protocol = "postgresql"


  host = {

    ipv4 = "10.0.0.5"

    network = {

      tunnel_id = var.tunnel_id

    }

  }


  tls_settings = {

    cert_verification_mode = "verify_ca"

  }

}


```

Valid values for `cert_verification_mode` are:

* `verify_full` (default)
* `verify_ca`
* `disabled`

Refer to [TLS certificate verification mode](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#tls-certificate-verification-mode) for details.

### Port configuration

For HTTP services, ports are optional and default to 80 (HTTP) and 443 (HTTPS). To enforce a single scheme, provide only one of `http_port` or `https_port`. Refer to [VPC Service configuration](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#vpc-service-configuration) for how scheme enforcement and port behavior work.

For TCP services, `tcp_port` is required.

## Workers binding configuration

Once a VPC Service exists, bind it to a Worker using the `vpc_service` binding type in the `bindings` array of a `cloudflare_worker_version` resource. This is equivalent to the [vpc\_services array in Wrangler configuration](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#workers-binding-configuration).

```

resource "cloudflare_worker_version" "my_worker_version" {

  account_id         = var.account_id

  worker_id          = cloudflare_worker.my_worker.id

  compatibility_date = "2025-02-21" # Set this to today's date

  main_module        = "worker.js"


  modules = [{

    name         = "worker.js"

    content_type = "application/javascript+module"

    content_file = "build/worker.js"

  }]


  bindings = [{

    type       = "vpc_service"

    name       = "PRIVATE_API"

    service_id = cloudflare_connectivity_directory_service.my_private_api.service_id

  }]

}


```

Multiple VPC Service bindings can be added to the same Worker:

```

bindings = [

  {

    type       = "vpc_service"

    name       = "PRIVATE_API"

    service_id = cloudflare_connectivity_directory_service.api.service_id

  },

  {

    type       = "vpc_service"

    name       = "PRIVATE_DATABASE"

    service_id = cloudflare_connectivity_directory_service.database.service_id

  }

]


```

The Worker code accesses each binding through `env.PRIVATE_API.fetch()` and `env.PRIVATE_DATABASE.fetch()`, as described in the [Workers Binding API](https://developers.cloudflare.com/workers-vpc/api/).

For more details on managing Workers and bindings with Terraform, refer to [Workers Infrastructure as Code](https://developers.cloudflare.com/workers/platform/infrastructure-as-code/).

## Data sources

The Terraform provider includes data sources for reading existing VPC Services without managing their lifecycle.

### Look up a single VPC Service

```

data "cloudflare_connectivity_directory_service" "existing" {

  account_id = var.account_id

  service_id = "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"

}


```

This is useful for binding to a VPC Service that is managed outside of your Terraform configuration (for example, created through the dashboard or Wrangler CLI).

### List VPC Services

```

data "cloudflare_connectivity_directory_services" "all_http" {

  account_id = var.account_id

  type       = "http"

}


data "cloudflare_connectivity_directory_services" "all_tcp" {

  account_id = var.account_id

  type       = "tcp"

}


```

## Resource schema reference

```

resource "cloudflare_connectivity_directory_service" "example" {

  # Required

  account_id = "your-account-id"        # Account identifier

  name       = "my-private-api"         # Human-readable name

  type       = "http"                   # Service type: "http" or "tcp"


  # HTTP-specific (optional, defaults to 80/443)

  http_port  = 80                       # HTTP port

  https_port = 443                      # HTTPS port


  # TCP-specific (tcp_port is required when type = "tcp")

  # tcp_port     = 5432                 # TCP port

  # app_protocol = "postgresql"         # Optional: "postgresql" or "mysql"


  host = {

    # Use hostname OR ipv4/ipv6, not both


    # Option A: Hostname-based

    hostname = "internal-api.example.com"

    resolver_network = {

      tunnel_id    = "tunnel-uuid"      # Required — Cloudflare Tunnel ID

      resolver_ips = ["10.0.0.53"]      # Optional — custom DNS resolver IPs

    }


    # Option B: IP-based

    # ipv4 = "10.0.1.50"               # IPv4 address

    # ipv6 = "fe80::1"                 # IPv6 address

    # network = {

    #   tunnel_id = "tunnel-uuid"      # Required — Cloudflare Tunnel ID

    # }

  }


  # Optional TLS settings

  # tls_settings = {

  #   cert_verification_mode = "verify_full"  # "verify_full", "verify_ca", or "disabled"

  # }


  # Read-only (computed by the API)

  # id         — Terraform resource ID

  # service_id — VPC Service ID (use this for Worker bindings)

  # created_at — Creation timestamp

  # updated_at — Last update timestamp

}


```

For the full schema, refer to the [Terraform registry documentation ↗](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/connectivity%5Fdirectory%5Fservice).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/configuration/vpc-services/","name":"VPC Services"}},{"@type":"ListItem","position":5,"item":{"@id":"/workers-vpc/configuration/vpc-services/terraform/","name":"Configure with Terraform"}}]}
```

---

---
title: Connect Workers to Cloudflare Mesh
description: Use a VPC Network binding with Cloudflare Mesh to reach private services from a Worker.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Connect Workers to Cloudflare Mesh

This example demonstrates how to use a VPC Network binding with [Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/) (formerly WARP Connector) to connect to any private service in your account from a Worker — without pre-registering individual hosts or specifying a Cloudflare Tunnel UUID.

When you bind to [Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/) using `network_id: "cf1:network"`, your Worker can reach any Mesh node, client device, subnet or hostname route announced through Cloudflare Tunnel or Cloudflare Mesh, or destination connected through a [Cloudflare WAN](https://developers.cloudflare.com/cloudflare-wan/) on-ramp (GRE, IPsec, or CNI).

## Prerequisites

* A [Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/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:

* [  wrangler.jsonc ](#tab-panel-11190)
* [  wrangler.toml ](#tab-panel-11191)

JSONC

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "mesh-gateway",

  "main": "src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-06-12",

  "vpc_networks": [

    {

      "binding": "MESH",

      "network_id": "cf1:network",

      "remote": true

    }

  ]

}


```

TOML

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "mesh-gateway"

main = "src/index.js"

# Set this to today's date

compatibility_date = "2026-06-12"


[[vpc_networks]]

binding = "MESH"

network_id = "cf1:network"

remote = true


```

With this single binding, your Worker can reach any service across all Cloudflare Tunnels, Mesh nodes, and Cloudflare WAN on-ramps in your account.

## 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.js

```

// Replace with the Mesh IP and port of your private service

const NODE_IP = "10.0.1.50";

const NODE_PORT = 8080;


export default {

  async fetch(request, env, ctx) {

    try {

      const response = await env.MESH.fetch(

        `http://${NODE_IP}:${NODE_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](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/), the URL you pass to `fetch()` determines the actual destination. You can reach any IP and port accessible through your Mesh network without creating separate bindings for each service.

## 3\. Deploy and test

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

Terminal window

```

npx wrangler deploy


```

Terminal window

```

# 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

* Learn more about [VPC Networks](https://developers.cloudflare.com/workers-vpc/configuration/vpc-networks/) configuration options
* Refer to the [Workers Binding API](https://developers.cloudflare.com/workers-vpc/api/) reference
* [Set up Cloudflare Mesh](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-mesh/get-started/) for your account
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/connect-to-cloudflare-mesh/","name":"Connect Workers to Cloudflare Mesh"}}]}
```

---

---
title: Access a private API or website
description: Use Workers VPC to fetch data from a private REST API behind Cloudflare Tunnel.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Access a private API or website

**Last reviewed:**  7 months ago 

This example demonstrates how to access a private REST API that is not exposed to the public internet. In this guide, we will configure a VPC Service for an internal API, create a Worker that makes requests to that API, and deploy the Worker to validate our changes.

## Prerequisites

* A virtual machine/EC2 instance running in your VPC/virtual network
* A private API or website running in your VPC/virtual network with security rules allowing access to the virtual machine that will be running `cloudflared`
* Workers account with Workers VPC access

## 1\. Set up Cloudflare Tunnel

A Cloudflare Tunnel creates a secure connection from your private network to Cloudflare. This tunnel will allow Workers to securely access your private resources.

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels) and select the **Tunnels** tab.
2. Select **Create** to create a new tunnel.
3. Enter a name for your tunnel (for example, `private-api-tunnel`) and select **Save tunnel**.
4. Choose your operating system and architecture. The dashboard will provide specific installation instructions for your environment.
5. Follow the provided commands to download and install `cloudflared` on your VM, and execute the service installation command with your unique token.

The dashboard will confirm when your tunnel is successfully connected. Note the tunnel ID for the next step.

## 2\. Create the Workers VPC Service

First, create a Workers VPC Service for your internal API:

Terminal window

```

npx wrangler vpc service create api-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --ipv4 10.0.1.50 \

  --http-port 8080


```

You can also create a VPC Service for a service using its hostname:

Terminal window

```

npx wrangler vpc service create api-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname internal-hostname.example.com


```

Note the service ID returned for the next step.

## 3\. Configure your Worker

Update your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-11192)
* [  wrangler.toml ](#tab-panel-11193)

JSONC

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "private-api-gateway",

  "main": "src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-06-12",

  "vpc_services": [

    {

      "binding": "INTERNAL_API",

      "service_id": "<YOUR_SERVICE_ID>",

      "remote": true

    }

  ]

}


```

TOML

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "private-api-gateway"

main = "src/index.js"

# Set this to today's date

compatibility_date = "2026-06-12"


[[vpc_services]]

binding = "INTERNAL_API"

service_id = "<YOUR_SERVICE_ID>"

remote = true


```

## 4\. Implement the Worker

In your Workers code, use the VPC Service binding in order to send requests to the service:

index.js

```

export default {

  async fetch(request, env, ctx) {

    try {

      // Fetch data from internal API and process it before returning

      const response = await env.INTERNAL_API.fetch("http://10.0.1.50:8080/api/data");


      // Use the response of the private API to perform more logic in Workers, before returning the final response

      return response;

    } catch (error) {

      return new Response("Service unavailable", { status: 503 });

    }

  },

};


```

This guide demonstrates how you could create a simple proxy in your Workers. However, you could use VPC Services to fetch APIs directly and manipulate the responses to enable you to build more full-stack and backend functionality on Workers.

## 5\. Deploy and test

Now, you can deploy and test your Worker that you have created:

Terminal window

```

npx wrangler deploy


```

Terminal window

```

# Test GET request

curl https://private-api-gateway.workers.dev


```

## Next steps

* Add [authentication and authorization](https://developers.cloudflare.com/workers/examples/auth-with-headers/)
* Implement [rate limiting](https://developers.cloudflare.com/durable-objects/api/)
* Set up [monitoring and alerting](https://developers.cloudflare.com/analytics/analytics-engine/)
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/private-api/","name":"Access a private API or website"}}]}
```

---

---
title: Connect to a private database
description: This example demonstrates how to query a private PostgreSQL database from a Worker using Workers VPC and Hyperdrive. The Worker connects to a database that is not exposed to the public Internet, with Hyperdrive providing connection pooling and query acceleration.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Connect to a private database

This example demonstrates how to query a private PostgreSQL database from a Worker using [Workers VPC](https://developers.cloudflare.com/workers-vpc/) and [Hyperdrive](https://developers.cloudflare.com/hyperdrive/). The Worker connects to a database that is not exposed to the public Internet, with Hyperdrive providing connection pooling and query acceleration.

## Prerequisites

* A PostgreSQL database running in your private network (for example, on port 5432)
* A [Cloudflare Tunnel](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/) connected to the private network where your database runs
* A Cloudflare account with Workers VPC access

## 1\. Set up a Cloudflare Tunnel

If you do not already have a tunnel running in the same network as your database, create one.

1. Go to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels) and select the **Tunnels** tab.
2. Select **Create** to create a tunnel.
3. Enter a name for your tunnel and select **Save tunnel**.
4. Choose your operating system and architecture. The dashboard will provide installation instructions.
5. Follow the provided commands to download, install, and run `cloudflared` with your unique token.

The tunnel must be able to reach your database host and port from within the private network. For full tunnel documentation, refer to [Cloudflare Tunnel for Workers VPC](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/).

## 2\. Create a TCP VPC Service

Create a VPC Service of type `tcp` that points to your database:

Terminal window

```

npx wrangler vpc service create my-postgres-db \

  --type tcp \

  --tcp-port 5432 \

  --app-protocol postgresql \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --ipv4 <YOUR_DATABASE_IP>


```

Replace `<YOUR_TUNNEL_ID>` with the tunnel ID from step 1 and `<YOUR_DATABASE_IP>` with the private IP address of your database (for example, `10.0.0.5`).

The command returns a service ID. Save this value for the next step.

Note

If your database uses a self-signed certificate, add `--cert-verification-mode verify_ca` to the command above. Refer to [TLS certificate verification mode](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/#tls-certificate-verification-mode) for all options.

## 3\. Create a Hyperdrive configuration

Use the `--service-id` flag to point Hyperdrive at the VPC Service you created:

Terminal window

```

npx wrangler hyperdrive create my-vpc-database \

  --service-id <YOUR_VPC_SERVICE_ID> \

  --database <DATABASE_NAME> \

  --user <DATABASE_USER> \

  --password <DATABASE_PASSWORD> \

  --scheme postgresql


```

Replace `<YOUR_VPC_SERVICE_ID>` with the service ID from step 2, and provide your database name, user, and password.

The command outputs a Hyperdrive configuration ID. Copy this for the next step.

## 4\. Bind Hyperdrive to a Worker

You must create a binding in your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/) for your Worker to connect to your Hyperdrive configuration. [Bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) allow your Workers to access resources, like Hyperdrive, on the Cloudflare developer platform.

To bind your Hyperdrive configuration to your Worker, add the following to the end of your Wrangler file:

* [  wrangler.jsonc ](#tab-panel-11194)
* [  wrangler.toml ](#tab-panel-11195)

JSONC

```

{

  "hyperdrive": [

    {

      "binding": "HYPERDRIVE",

      "id": "<YOUR_DATABASE_ID>" // the ID associated with the Hyperdrive you just created

    }

  ]

}


```

TOML

```

[[hyperdrive]]

binding = "HYPERDRIVE"

id = "<YOUR_DATABASE_ID>"


```

Specifically:

* The value (string) you set for the `binding` (binding name) will be used to reference this database in your Worker. In this tutorial, name your binding `HYPERDRIVE`.
* The binding must be [a valid JavaScript variable name ↗](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar%5Fand%5Ftypes#variables). For example, `binding = "hyperdrive"` or `binding = "productionDB"` would both be valid names for the binding.
* Your binding is available in your Worker at `env.<BINDING_NAME>`.

If you wish to use a local database during development, you can add a `localConnectionString` to your Hyperdrive configuration with the connection string of your database:

* [  wrangler.jsonc ](#tab-panel-11196)
* [  wrangler.toml ](#tab-panel-11197)

JSONC

```

{

  "hyperdrive": [

    {

      "binding": "HYPERDRIVE",

      "id": "<YOUR_DATABASE_ID>", // the ID associated with the Hyperdrive you just created

      "localConnectionString": "<LOCAL_DATABASE_CONNECTION_URI>"

    }

  ]

}


```

TOML

```

[[hyperdrive]]

binding = "HYPERDRIVE"

id = "<YOUR_DATABASE_ID>"

localConnectionString = "<LOCAL_DATABASE_CONNECTION_URI>"


```

Note

Learn more about setting up [Hyperdrive for local development](https://developers.cloudflare.com/hyperdrive/configuration/local-development/).

## 5\. Query the database

Install the `node-postgres` driver:

 npm  yarn  pnpm  bun 

```
npm i pg@>8.16.3
```

```
yarn add pg@>8.16.3
```

```
pnpm add pg@>8.16.3
```

```
bun add pg@>8.16.3
```

Note

The minimum version of `node-postgres` required for Hyperdrive is `8.16.3`.

If using TypeScript, install the types package:

 npm  yarn  pnpm  bun 

```
npm i -D @types/pg
```

```
yarn add -D @types/pg
```

```
pnpm add -D @types/pg
```

```
bun add -d @types/pg
```

Add the required Node.js compatibility flags and Hyperdrive binding to your `wrangler.jsonc` file:

* [  wrangler.jsonc ](#tab-panel-11198)
* [  wrangler.toml ](#tab-panel-11199)

JSONC

```

{

  // required for database drivers to function

  "compatibility_flags": [

    "nodejs_compat"

  ],

  // Set this to today's date

  "compatibility_date": "2026-06-12",

  "hyperdrive": [

    {

      "binding": "HYPERDRIVE",

      "id": "<your-hyperdrive-id-here>"

    }

  ]

}


```

TOML

```

compatibility_flags = [ "nodejs_compat" ]

# Set this to today's date

compatibility_date = "2026-06-12"


[[hyperdrive]]

binding = "HYPERDRIVE"

id = "<your-hyperdrive-id-here>"


```

Create a new `Client` instance and pass the Hyperdrive `connectionString`:

TypeScript

```

// filepath: src/index.ts

import { Client } from "pg";


export default {

  async fetch(

    request: Request,

    env: Env,

    ctx: ExecutionContext,

  ): Promise<Response> {

    // Create a new client instance for each request. Hyperdrive maintains the

    // underlying database connection pool, so creating a new client is fast.

    const client = new Client({

      connectionString: env.HYPERDRIVE.connectionString,

    });


    try {

      // Connect to the database

      await client.connect();


      // Perform a simple query

      const result = await client.query("SELECT * FROM pg_tables");


      return Response.json({

        success: true,

        result: result.rows,

      });

    } catch (error: any) {

      console.error("Database error:", error.message);


      return new Response("Internal error occurred", { status: 500 });

    }

  },

};


```

## 6\. Deploy and test

Deploy your Worker:

Terminal window

```

npx wrangler deploy


```

Send a request to verify the connection:

Terminal window

```

curl https://<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev


```

A successful response returns a JSON array of rows from your database.

## Next steps

* Learn more about [how Hyperdrive works](https://developers.cloudflare.com/hyperdrive/concepts/how-hyperdrive-works/)
* Configure [query caching](https://developers.cloudflare.com/hyperdrive/concepts/query-caching/) for Hyperdrive
* Review [VPC Service configuration options](https://developers.cloudflare.com/workers-vpc/configuration/vpc-services/) including TLS certificate verification
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/private-database/","name":"Connect to a private database"}}]}
```

---

---
title: Access a private S3 bucket
description: Use Workers VPC to read objects from a private S3-compatible bucket behind Cloudflare Tunnel.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Access a private S3 bucket

**Last reviewed:**  7 months ago 

This example demonstrates how to access a private S3 bucket that is not exposed to the public internet. In this guide, we will configure a Workers VPC Service for an internal S3-compatible storage service, create a Worker that makes requests to that bucket, and deploy the Worker to validate our changes.

## Prerequisites

* A private S3-compatible storage service running in your VPC/virtual network (such as AWS S3 VPC endpoint, MinIO, or similar)
* A virtual machine/EC2 instance running in the same VPC as your S3 VPC endpoint
* Workers account with Workers VPC access

## 1\. Set up Cloudflare Tunnel

A Cloudflare Tunnel creates a secure connection from your private network to Cloudflare. This tunnel will allow Workers to securely access your private resources.

1. Navigate to the [Workers VPC dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels) and select the **Tunnels** tab.
2. Select **Create** to create a new tunnel.
3. Enter a name for your tunnel (for example, `s3-tunnel`) and select **Save tunnel**.
4. Choose your operating system and architecture. The dashboard will provide specific installation instructions for your environment.
5. Follow the provided commands to download and install `cloudflared` on your VM, and execute the service installation command with your unique token.

The dashboard will confirm when your tunnel is successfully connected. Note the tunnel ID for the next step.

## 2\. Create the Workers VPC Service

First, create a Workers VPC Service for your internal S3 storage:

Terminal window

```

npx wrangler vpc service create s3-storage \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname s3.us-west-2.amazonaws.com


```

You can also create a Workers VPC Service using an IP address (for example, if using MinIO):

Terminal window

```

npx wrangler vpc service create s3-storage \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --ipv4 10.0.1.60 \

  --http-port 9000


```

Note the service ID returned for the next step.

## 3\. Configure S3 bucket policy

Configure your S3 bucket to allow anonymous access from your VPC endpoint. This works for unencrypted S3 objects:

```

{

  "Version": "2012-10-17",

  "Statement": [

    {

      "Sid": "AllowAnonymousAccessFromVPCE",

      "Effect": "Allow",

      "Principal": "*",

      "Action": ["s3:GetObject", "s3:ListBucket"],

      "Resource": [

        "arn:aws:s3:::your-bucket-name",

        "arn:aws:s3:::your-bucket-name/*"

      ],

      "Condition": {

        "StringEquals": {

          "aws:sourceVpce": "vpce-your-endpoint-id"

        }

      }

    }

  ]

}


```

### Testing S3 access directly

You can test S3 access directly from the VM where your Cloudflare Tunnel is running to verify the bucket policy is working correctly. These commands should work without any AWS credentials:

Terminal window

```

# Test listing bucket contents

curl -i https://s3.us-west-2.amazonaws.com/your-bucket-name/


# Test downloading a specific file

curl -i https://your-bucket-name.s3.us-west-2.amazonaws.com/test-file.txt


```

## 4\. Configure your Worker

Update your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-11200)
* [  wrangler.toml ](#tab-panel-11201)

JSONC

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "private-s3-gateway",

  "main": "src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-06-12",

  "vpc_services": [

    {

      "binding": "S3_STORAGE",

      "service_id": "<YOUR_SERVICE_ID>"

    }

  ]

}


```

TOML

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "private-s3-gateway"

main = "src/index.js"

# Set this to today's date

compatibility_date = "2026-06-12"


[[vpc_services]]

binding = "S3_STORAGE"

service_id = "<YOUR_SERVICE_ID>"


```

## 5\. Implement the Worker

In your Workers code, use the Workers VPC Service binding in order to send requests to the service:

index.js

```

export default {

  async fetch(request, env, ctx) {

    try {

      // Fetch a file from the private S3 bucket via VPC endpoint

      const response = await env.S3_STORAGE.fetch("https://s3.us-west-2.amazonaws.com/my-bucket/data.json");


      // Use the response from S3 to perform more logic in Workers, before returning the final response

      return response;

    } catch (error) {

      return new Response("Storage unavailable", { status: 503 });

    }

  },

};


```

This guide demonstrates how you could access private object storage from your Workers. You could use Workers VPC Services to fetch files directly and manipulate the responses to enable you to build more full-stack and backend functionality on Workers.

## 6\. Deploy and test

Now, you can deploy and test your Worker that you have created:

Terminal window

```

npx wrangler deploy


```

Terminal window

```

# Test GET request

curl https://private-s3-gateway.workers.dev


```

## Next steps

* Add [authentication and authorization](https://developers.cloudflare.com/workers/examples/auth-with-headers/)
* Implement [rate limiting](https://developers.cloudflare.com/durable-objects/api/)
* Set up [monitoring and alerting](https://developers.cloudflare.com/analytics/analytics-engine/)
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/private-s3-bucket/","name":"Access a private S3 bucket"}}]}
```

---

---
title: Route to private services from Workers
description: Build a Worker gateway that routes and load balances across multiple private VPC Services.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Route to private services from Workers

**Last reviewed:**  7 months ago 

This example shows how to use Workers VPC to create a centralized gateway that routes requests based on URL paths, provides authentication and rate limiting, and load balances across internal services.

## Prerequisites

* Multiple private APIs or services running in your VPC/virtual network (we'll use a user service and orders service)
* Cloudflare Tunnel configured and running (follow the [Get Started guide](https://developers.cloudflare.com/workers-vpc/get-started/#2-set-up-cloudflare-tunnel) to set up or [create a tunnel from the dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers/vpc/tunnels))
* Workers account with Workers VPC access

## 1\. Create the VPC Services

First, create services for your internal APIs using hostnames:

Terminal window

```

# Create user service

npx wrangler vpc service create user-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname user-api.internal.example.com


# Create orders service

npx wrangler vpc service create order-service \

  --type http \

  --tunnel-id <YOUR_TUNNEL_ID> \

  --hostname orders-api.internal.example.com


```

Note the service IDs returned for the next step.

## 2\. Configure your Worker

Update your Wrangler configuration file:

* [  wrangler.jsonc ](#tab-panel-11202)
* [  wrangler.toml ](#tab-panel-11203)

JSONC

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "api-gateway",

  "main": "src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-06-12",

  "vpc_services": [

    {

      "binding": "USER_SERVICE",

      "service_id": "<YOUR_USER_SERVICE_ID>"

    },

    {

      "binding": "ORDER_SERVICE",

      "service_id": "<YOUR_ORDER_SERVICE_ID>"

    }

  ]

}


```

TOML

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "api-gateway"

main = "src/index.js"

# Set this to today's date

compatibility_date = "2026-06-12"


[[vpc_services]]

binding = "USER_SERVICE"

service_id = "<YOUR_USER_SERVICE_ID>"


[[vpc_services]]

binding = "ORDER_SERVICE"

service_id = "<YOUR_ORDER_SERVICE_ID>"


```

## 3\. Implement the Worker

In your Workers code, use the VPC Service bindings to route requests to the appropriate services:

index.js

```

export default {

  async fetch(request, env, ctx) {

    const url = new URL(request.url);


    // Route to internal services

    if (url.pathname.startsWith('/api/users')) {

      const response = await env.USER_SERVICE.fetch("https://user-api.internal.example.com" + url.pathname);

      return response;

    } else if (url.pathname.startsWith('/api/orders')) {

      const response = await env.ORDER_SERVICE.fetch("https://orders-api.internal.example.com" + url.pathname);

      return response;

    }


    return new Response('Not Found', { status: 404 });

  },

};


```

## 4\. Deploy and test

Now, you can deploy and test your Worker:

Terminal window

```

npx wrangler deploy


```

Terminal window

```

# Test user service requests

curl https://api-gateway.workers.dev/api/users


# Test orders service requests

curl https://api-gateway.workers.dev/api/orders


```

## Next steps

* Add [authentication and authorization](https://developers.cloudflare.com/workers/examples/auth-with-headers/)
* Implement [rate limiting](https://developers.cloudflare.com/durable-objects/api/)
* Set up [monitoring and alerting](https://developers.cloudflare.com/analytics/analytics-engine/)
* Explore [other examples](https://developers.cloudflare.com/workers-vpc/examples/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/examples/","name":"Examples"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/examples/route-across-private-services/","name":"Route to private services from Workers"}}]}
```

---

---
title: Limits
description: Account-level limits for VPC Services and applicable Workers request limits.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Limits

## Service limits

| Resource                 | Limit |
| ------------------------ | ----- |
| VPC Services per account | 1000  |

Standard Workers limits apply for request size, timeout, and subrequests.

Note

Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/limits/","name":"Limits"}}]}
```

---

---
title: Pricing
description: Workers VPC pricing details and free open beta availability.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Pricing

Workers VPC requires a Workers plan. See [Workers pricing](https://developers.cloudflare.com/workers/platform/pricing/) for current rates.

Free during Open Beta

Workers VPC is free during the open beta period. Standard Workers pricing applies for compute time and requests.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/pricing/","name":"Pricing"}}]}
```

---

---
title: Troubleshoot and debug
description: Debug Workers VPC connection errors, tunnel issues, and common configuration problems.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshoot and debug

Troubleshoot and debug errors commonly associated with Workers VPC.

## Connection error codes

When Workers VPC cannot establish a connection to your private service, `fetch()` will throw an exception with an error code describing what went wrong. These error codes are also visible in the **Metrics** tab of your VPC Service in the Cloudflare dashboard.

Errors are grouped into three categories based on the likely cause. These categories match the labels shown in the **Metrics** tab of your VPC Service in the dashboard.

* **Bad Upstream** — Your tunnel or private service is not reachable. Check tunnel health, service availability, and network/TLS configuration.
* **Client** — Your VPC Service configuration or Worker code caused the failure. Check your target hostname and Worker request behavior.
* **Internal** — A Cloudflare infrastructure issue. Contact Cloudflare support if this persists.

### Bad Upstream errors

These errors indicate that Cloudflare attempted to reach your private service but the connection failed. The tunnel may be down, the service may not be listening, or there is a network or TLS issue between Cloudflare and your origin.

| Error code                  | Description                                                                    | Recommended fix                                                                                                                                                                                                                                                         |
| --------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| connection\_refused         | Your private service refused the TCP connection.                               | Verify your service is running and listening on the expected port. Check firewall rules.                                                                                                                                                                                |
| connection\_terminated      | The connection was closed by your service before a response was received.      | Check your service logs for crashes or resource exhaustion.                                                                                                                                                                                                             |
| connection\_timeout         | The connection attempt to your service timed out.                              | Verify your service is reachable from the tunnel. Check for network latency or firewall rules blocking traffic.                                                                                                                                                         |
| connection\_limit\_reached  | The maximum number of concurrent connections to your service has been reached. | Scale your service to handle more connections, or reduce connection concurrency in your Worker.                                                                                                                                                                         |
| destination\_unavailable    | Your service is considered unavailable.                                        | Verify your tunnel is running and your service is healthy.                                                                                                                                                                                                              |
| destination\_not\_found     | No route could be determined for this request.                                 | Check that your VPC Service configuration points to a valid host and that your tunnel is configured to route traffic to it.                                                                                                                                             |
| destination\_ip\_prohibited | The destination IP address is prohibited.                                      | Verify the IP address configured for your VPC Service is correct and not on a restricted list.                                                                                                                                                                          |
| destination\_ip\_unroutable | No network route exists to the destination IP.                                 | Check that the IP address is correct and reachable from within your private network.                                                                                                                                                                                    |
| proxy\_loop\_detected       | The request would be forwarded back to the same proxy, creating a loop.        | Review your VPC Service and tunnel configuration for circular routing.                                                                                                                                                                                                  |
| dns\_error                  | DNS resolution failed (for example, SERVFAIL).                                 | Check that the hostname configured for your VPC Service is resolvable from within your private network. Verify your DNS resolver is working correctly. Refer to [Tunnel errors](#tunnel-errors) for common DNS causes.                                                  |
| dns\_timeout                | DNS resolution timed out.                                                      | Check your DNS resolver is reachable and responding. Consider configuring a custom DNS resolver in your VPC Service settings.                                                                                                                                           |
| tls\_protocol\_error        | A TLS handshake or protocol error occurred when connecting to your service.    | Verify your service's TLS configuration. Ensure the TLS version and cipher suites are compatible.                                                                                                                                                                       |
| tls\_certificate\_error     | Your service's TLS certificate failed verification.                            | Ensure your service presents a valid certificate from a [publicly trusted CA](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) or a [Cloudflare Origin CA certificate](https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/). |
| http\_request\_error        | An HTTP request error occurred.                                                | Check your service logs for details on what caused the error response.                                                                                                                                                                                                  |
| http\_upgrade\_failed       | An HTTP upgrade (for example, WebSocket) failed.                               | Verify your service supports the requested protocol upgrade.                                                                                                                                                                                                            |
| http\_request\_denied       | The request was rejected by policy before being forwarded.                     | Review your service's access policies and configuration.                                                                                                                                                                                                                |
| http\_protocol\_error       | An HTTP protocol error occurred when communicating with your service.          | Check that your service is responding with valid HTTP.                                                                                                                                                                                                                  |
| http\_response\_incomplete  | Your service returned an incomplete HTTP response.                             | Check your service for issues that may cause it to close connections mid-response.                                                                                                                                                                                      |

### Client errors

These errors indicate a problem with your VPC Service setup or your Worker's behavior — not with the private service itself.

| Error code                 | Description                                                                    | Recommended fix                                                                                                     |
| -------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| dns\_error (NXDOMAIN)      | The hostname configured for your VPC Service does not exist in DNS.            | Verify the hostname in your VPC Service configuration is correct and that a DNS record exists for it.               |
| connection\_read\_timeout  | The connection was established but no data was received within the time limit. | Check your Worker code for stalled or slow requests. Ensure your Worker is reading the response in a timely manner. |
| connection\_write\_timeout | Data could not be written to the connection (buffers full).                    | Check your Worker code for slow consumption of response data.                                                       |
| rate\_limited              | The connection rate limit to this origin has been exceeded.                    | Reduce the rate of new connections from your Worker to this service.                                                |

Note

The `dns_error` code can appear as either a **Bad Upstream** error or a **Client** error depending on the DNS failure type. An NXDOMAIN response (hostname does not exist) is classified as a Client error because it typically means the VPC Service hostname is misconfigured. All other DNS failures (SERVFAIL, timeouts, and similar) are classified as Bad Upstream errors.

### Internal errors

These errors indicate an issue within Cloudflare's infrastructure that is not caused by your configuration or your origin service.

| Error code             | Description                                             | Recommended fix                                                                                                                   |
| ---------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| proxy\_internal\_error | An internal error occurred within the Cloudflare proxy. | This is not caused by your configuration. If this error persists, contact [Cloudflare support ↗](https://support.cloudflare.com). |

## Tunnel errors

Workers VPC may return errors at runtime when connecting to private services through Cloudflare Tunnel.

| Error Message                   | Details                                                                                                                                                                                                                                                                                                      | Recommended fixes                                                                                                                                                                                                                                                                                                           |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Error: ProxyError: dns\_error   | DNS resolution failed when attempting to connect to your private service through the tunnel.                                                                                                                                                                                                                 | This error may occur if your cloudflared version is outdated. Ensure you are running cloudflared version 2025.7.0 or later (latest version recommended). See [Cloudflare Tunnel update instructions](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/downloads/update-cloudflared/). |
| Error: ProxyError: dns\_error   | Cloudflare Tunnel may be configured with http2 protocol (TUNNEL\_TRANSPORT\_PROTOCOL:http2), which works for Cloudflare Zero Trust [(see note)](https://developers.cloudflare.com/workers-vpc/configuration/tunnel/#create-and-run-tunnel-cloudflared) traffic but prevents DNS resolution from Workers VPC. | Workers VPC requires Cloudflare Tunnel to connect using the [QUIC transport protocol](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/run-parameters/#protocol). Ensure outbound UDP traffic on port 7844 is allowed through your firewall.                        |
| Requests not staying within VPC | Worker requests using .fetch() with a public hostname are routing out of the VPC to the hostname configured for the VPC Service.                                                                                                                                                                             | Ensure your Worker code and the VPC Service use the internal VPC hostname for backend services, not a public hostname.                                                                                                                                                                                                      |

## Permission errors

If you cannot view, create, or bind VPC Services and Tunnels in the dashboard or via Wrangler, ensure your user has the required roles.

Workers VPC uses the following account roles:

* `Connectivity Directory Read` to view Workers VPC Services and Tunnels.
* `Connectivity Directory Bind` to list, read, and bind VPC Services in Workers.
* `Connectivity Directory Admin` to create, update, and delete VPC Services, and bind directly to tunnels through a VPC Network binding.

For role definitions, refer to [Roles](https://developers.cloudflare.com/fundamentals/manage-members/roles/#account-scoped-roles).

If your roles were recently updated and commands are still failing, refresh Wrangler authentication:

Terminal window

```

npx wrangler logout

npx wrangler login


```

If you authenticate with an API token (`CLOUDFLARE_API_TOKEN`), ensure the token belongs to a user with the required roles.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/troubleshooting/","name":"Troubleshoot and debug"}}]}
```

---

---
title: Wrangler commands
description: Wrangler CLI commands for creating and managing Workers VPC services.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Wrangler commands

The following [Wrangler commands](https://developers.cloudflare.com/workers/wrangler/) allow you to manage Workers VPC services.

## `vpc service create`

Create a new VPC service

* [  npm ](#tab-panel-11208)
* [  pnpm ](#tab-panel-11209)
* [  yarn ](#tab-panel-11210)

Terminal window

```

npx wrangler vpc service create [NAME]


```

Terminal window

```

pnpm wrangler vpc service create [NAME]


```

Terminal window

```

yarn wrangler vpc service create [NAME]


```

* `[NAME]` ` string ` required  
The name of the VPC service
* `--type` ` string ` required  
The type of the VPC service
* `--tcp-port` ` number `  
TCP port number
* `--app-protocol` ` string `  
Application protocol for the TCP service
* `--http-port` ` number `  
HTTP port (default: 80)
* `--https-port` ` number `  
HTTPS port number (default: 443)
* `--ipv4` ` string `  
IPv4 address for the host \[conflicts with --ipv6\]
* `--ipv6` ` string `  
IPv6 address for the host \[conflicts with --ipv4\]
* `--hostname` ` string `  
Hostname for the host
* `--resolver-ips` ` string `  
Comma-separated list of resolver IPs
* `--tunnel-id` ` string ` required  
UUID of the Cloudflare tunnel
* `--cert-verification-mode` ` string `  
TLS certificate verification mode for the connection to the origin

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources
* `--install-skills` ` boolean ` default: false  
Install Cloudflare agents skills, if not already present, without asking the user for confirmation

## `vpc service delete`

Delete a VPC service

* [  npm ](#tab-panel-11211)
* [  pnpm ](#tab-panel-11212)
* [  yarn ](#tab-panel-11213)

Terminal window

```

npx wrangler vpc service delete [SERVICE-ID]


```

Terminal window

```

pnpm wrangler vpc service delete [SERVICE-ID]


```

Terminal window

```

yarn wrangler vpc service delete [SERVICE-ID]


```

* `[SERVICE-ID]` ` string ` required  
The ID of the service to delete

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources
* `--install-skills` ` boolean ` default: false  
Install Cloudflare agents skills, if not already present, without asking the user for confirmation

## `vpc service get`

Get a VPC service

* [  npm ](#tab-panel-11214)
* [  pnpm ](#tab-panel-11215)
* [  yarn ](#tab-panel-11216)

Terminal window

```

npx wrangler vpc service get [SERVICE-ID]


```

Terminal window

```

pnpm wrangler vpc service get [SERVICE-ID]


```

Terminal window

```

yarn wrangler vpc service get [SERVICE-ID]


```

* `[SERVICE-ID]` ` string ` required  
The ID of the VPC service

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources
* `--install-skills` ` boolean ` default: false  
Install Cloudflare agents skills, if not already present, without asking the user for confirmation

## `vpc service list`

List VPC services

* [  npm ](#tab-panel-11217)
* [  pnpm ](#tab-panel-11218)
* [  yarn ](#tab-panel-11219)

Terminal window

```

npx wrangler vpc service list


```

Terminal window

```

pnpm wrangler vpc service list


```

Terminal window

```

yarn wrangler vpc service list


```

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources
* `--install-skills` ` boolean ` default: false  
Install Cloudflare agents skills, if not already present, without asking the user for confirmation

## `vpc service update`

Update a VPC service

* [  npm ](#tab-panel-11220)
* [  pnpm ](#tab-panel-11221)
* [  yarn ](#tab-panel-11222)

Terminal window

```

npx wrangler vpc service update [SERVICE-ID]


```

Terminal window

```

pnpm wrangler vpc service update [SERVICE-ID]


```

Terminal window

```

yarn wrangler vpc service update [SERVICE-ID]


```

* `[SERVICE-ID]` ` string ` required  
The ID of the VPC service to update
* `--name` ` string ` required  
The name of the VPC service
* `--type` ` string ` required  
The type of the VPC service
* `--tcp-port` ` number `  
TCP port number
* `--app-protocol` ` string `  
Application protocol for the TCP service
* `--http-port` ` number `  
HTTP port (default: 80)
* `--https-port` ` number `  
HTTPS port number (default: 443)
* `--ipv4` ` string `  
IPv4 address for the host \[conflicts with --ipv6\]
* `--ipv6` ` string `  
IPv6 address for the host \[conflicts with --ipv4\]
* `--hostname` ` string `  
Hostname for the host
* `--resolver-ips` ` string `  
Comma-separated list of resolver IPs
* `--tunnel-id` ` string ` required  
UUID of the Cloudflare tunnel
* `--cert-verification-mode` ` string `  
TLS certificate verification mode for the connection to the origin

Global flags

* `--v` ` boolean ` alias: --version  
Show version number
* `--cwd` ` string `  
Run as if Wrangler was started in the specified directory instead of the current working directory
* `--config` ` string ` alias: --c  
Path to Wrangler configuration file
* `--env` ` string ` alias: --e  
Environment to use for operations, and for selecting .env and .dev.vars files
* `--env-file` ` string `  
Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files
* `--experimental-provision` ` boolean ` aliases: --x-provision default: true  
Experimental: Enable automatic resource provisioning
* `--experimental-auto-create` ` boolean ` alias: --x-auto-create default: true  
Automatically provision draft bindings with new resources
* `--install-skills` ` boolean ` default: false  
Install Cloudflare agents skills, if not already present, without asking the user for confirmation

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers-vpc/","name":"Workers VPC"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers-vpc/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers-vpc/reference/wrangler-commands/","name":"Wrangler commands"}}]}
```
