Skip to content

Connect to a private database using Workers VPC (Recommended)

Workers VPC provides a way to connect Hyperdrive to a private database without configuring Cloudflare Access applications or service tokens. Instead, you create a TCP VPC Service that points to your database and pass its service ID to Hyperdrive.

For the Tunnel and Access approach, refer to Connect to a private database using Tunnel.

How it works

When your database is isolated within a private network (such as a virtual private cloud or an on-premise network), you must enable a secure connection from your network to Cloudflare.

  • Cloudflare Tunnel is used to establish a secure outbound connection from your private network to Cloudflare.
  • A VPC Service is used to route traffic from your Worker through the tunnel to your database, without requiring Cloudflare Access applications or service tokens.

A request from the Cloudflare Worker to the origin database goes through Hyperdrive, the VPC Service, and the Cloudflare Tunnel established by cloudflared. cloudflared must be running in the private network in which your database is accessible.

flowchart LR
    A[Cloudflare Worker] --> B[Hyperdrive] --> C[VPC Service] --> D[Cloudflare Tunnel] --> E[Private Database]

Before you start

All of the tutorials assume you have already completed the Get started guide, which gets you set up with a Cloudflare Workers account, C3, and Wrangler.

Prerequisites

  • A database in your private network, configured to use TLS/SSL.
  • A Cloudflare Tunnel running in a network that can reach your database.
  • The Connectivity Directory Admin role on your Cloudflare account to create VPC Services.

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

2. Create a TCP VPC Service

Create a VPC Service of type tcp that points to your database. Set the --app-protocol flag to postgresql or mysql so that Hyperdrive can optimize connections.

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.
  • <YOUR_DATABASE_IP> with the private IP address of your database (for example, 10.0.0.5). You can also use --hostname with a DNS name instead of --ipv4.

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

You can also create a TCP VPC Service from the Workers VPC dashboard. Refer to VPC Services for all configuration options.

TLS certificate verification

Unlike Hyperdrive, which does not verify the origin server certificate by default, Workers VPC defaults to verify_full — it verifies both the certificate chain and the hostname. If your database uses a self-signed certificate or a certificate from a private certificate authority (CA), the TLS handshake will fail unless you adjust the verification mode.

For databases with self-signed certificates, add --cert-verification-mode when creating the VPC Service:

  • verify_ca — Verifies the certificate chain but skips hostname verification. Use this when your database has a certificate signed by a CA you control but the hostname does not match the certificate.
  • disabled — Skips certificate verification entirely. Use this only for development or testing.

For example, to create a VPC Service for a PostgreSQL database with a self-signed certificate:

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> \
--cert-verification-mode verify_ca

To update an existing VPC Service, use wrangler vpc service update with the same flag.

For the full list of verification modes, refer to TLS certificate verification mode.

3. Create a Hyperdrive configuration

Use the --service-id flag to point Hyperdrive at the VPC Service you created. When you use --service-id, you do not provide --origin-host, --origin-port, or --connection-string. Hyperdrive routes traffic through the VPC Service instead.

Terminal window
npx wrangler hyperdrive create <YOUR_CONFIG_NAME> \
--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.
  • <DATABASE_NAME> with the name of your database.
  • <DATABASE_USER> and <DATABASE_PASSWORD> with your database credentials.

If successful, the command will output a Hyperdrive configuration with an id field. Copy this ID for the next step.

4. Bind Hyperdrive to a Worker

You must create a binding in your Wrangler configuration file for your Worker to connect to your Hyperdrive configuration. 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:

JSONC
{
"hyperdrive": [
{
"binding": "HYPERDRIVE",
"id": "<YOUR_DATABASE_ID>" // the ID associated with the Hyperdrive you just created
}
]
}

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. 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:

JSONC
{
"hyperdrive": [
{
"binding": "HYPERDRIVE",
"id": "<YOUR_DATABASE_ID>", // the ID associated with the Hyperdrive you just created
"localConnectionString": "<LOCAL_DATABASE_CONNECTION_URI>"
}
]
}

5. Query the database

Use node-postgres (pg) to send a test query.

Install the node-postgres driver:

npm i pg@>8.16.3

If using TypeScript, install the types package:

npm i -D @types/pg

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

JSONC
{
// required for database drivers to function
"compatibility_flags": [
"nodejs_compat"
],
// Set this to today's date
"compatibility_date": "2026-05-05",
"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 });
}
},
};

Deploy your Worker:

Terminal window
npx wrangler deploy

If you receive a list of pg_tables from your database when you access your deployed Worker, Hyperdrive is connected to your private database through Workers VPC.

Next steps