Hyperdriveとは何か——TCP接続とコネクションプーリング、そしてローカル開発

HyperdriveはWorkersから既存のPostgres/MySQLへ接続するためのCloudflareのサービスで、単なる「DB接続用のバインディング」ではありません。Workersという実行環境の制約を踏まえた、かなり専用色の強い設計になっています。

Hyperdriveが解決している問題

Workersはリクエストのたびに短命な実行環境が立ち上がる、いわゆるedge/statelessな実行モデルです。ここに従来型のPostgresやMySQLへ毎回新規にTCP接続を張りにいくと、TCPハンドシェイク・TLSネゴシエーション・DB側の認証という一連のコストを、リクエストごとに払うことになります。データベースが地理的に離れていればいるほど、この往復コストは無視できません。

Hyperdriveは、Cloudflareのエッジ側でデータベースへのコネクションプールを維持し、Workerからのクエリをそのプールに中継することでこの問題を解決します。Worker自身が毎回新規接続を張るのではなく、すでに温まっている接続を使い回せるイメージです。

TCP接続にそのまま対応している

Hyperdriveの大きな特徴は、PostgresやMySQLの生のワイヤープロトコル(TCP)にそのまま対応していることです。内部的にはcloudflare:socketsによるTCPソケットの仕組みを使っており、pgmysql2、Prisma、Drizzle ORMといった、既存のTCPベースのドライバーをほぼそのまま使えます。REST APIのような別プロトコルへの書き換えが不要な点は、既存資産を持つプロダクトにとって移行コストの低さにつながります。

// Drizzle + node-postgresドライバーでHyperdrive経由の接続を使う例
import { drizzle } from 'drizzle-orm/node-postgres';
import { Client } from 'pg';

export async function getDb(platform: App.Platform) {
  const client = new Client({
    connectionString: platform.env.HYPERDRIVE.connectionString,
  });
  await client.connect();
  return drizzle(client);
}

コネクションプーリングとクエリキャッシュ

Hyperdriveはコネクションプーリングに加えて、クエリキャッシュの機能も持っています。読み取りクエリの結果を一定時間キャッシュし、同一クエリが短時間に繰り返されるケースではデータベースへの往復自体を省略できます。書き込みクエリはキャッシュされず、キャッシュのTTLも設定で調整できるため、リアルタイム性が必要なデータかどうかに応じて使い分けが可能です。

対応するデータベースはPostgres・MySQL互換であれば基本的に何でもよく、自前で立てたインスタンスに限らず、RDSのようなマネージドDB、Supabaseが提供するPostgres、Neon、PlanetScaleのMySQLなど、標準的な接続文字列を発行できるサービスであれば組み合わせられます。

代替案:HTTPベースのAPIという選択肢

Hyperdriveを使わない選択肢も知っておく価値があります。SupabaseはPostgRESTベースのREST/GraphQL APIを標準で提供しており、これを使えばTCP接続そのものが不要になります。fetchだけで完結するため、Workers環境とは非常に相性がよく、Hyperdriveのセットアップすら要りません。Neonも@neondatabase/serverlessというHTTP/WebSocket経由でクエリを実行できるドライバーを提供しており、同様にTCPを避けられます。

つまり、外部DBへの接続方法は「TCPドライバー+Hyperdrive」と「提供元のHTTPベースAPI」の2択になるケースが多く、既存のTCPベースの資産をそのまま活かしたいならHyperdrive、新規に組むならHTTPベースのAPIも比較検討する価値がある、という整理になります。

ローカル開発での扱い方

TCP接続を扱うサービスである以上、Hyperdriveのローカル開発にはD1やKVとは違う制約があります。

D1/KV/R2は「put/get/queryするだけのストレージAPI」なので、実際のworkerdランタイムなしでもMiniflareが完全にエミュレートできます。一方Hyperdriveはランタイムレベルのネットワーキング機能を使うため、workerd本体のソケット実装が必要です。SvelteKitのVite開発サーバー(@sveltejs/adapter-cloudflareが使うgetPlatformProxy())はworkerdそのものを起動しないため、Hyperdriveバインディングは本番相当の値ではなく単純なパススルー値しか返せません。検証したい場合はwrangler devを使う必要があります。

その上で、HyperdriveにはlocalConnectionStringという設定があり、本物のHyperdriveプロキシは経由しないものの、ローカル(または任意)のPostgres/MySQLに直結する形でのローカル開発が可能です。

// wrangler.jsonc
{
  "hyperdrive": [
    {
      "binding": "HYPERDRIVE",
      "id": "xxxx",
      "localConnectionString": "postgres://user:pass@localhost:5432/mydb"
    }
  ]
}

Cloudflareの公式サポート表ではHyperdriveは「リモート必須」寄りに書かれていますが、このlocalConnectionStringによって、実質的にはローカルのデータベースを使った開発が可能になっています。ただし接続先をローカルDBに切り替えているだけで、Hyperdriveバインディング自体がネットワーキングAPIであることは変わらないため、wrangler devでの起動が前提になる点は変わりません。

Alcogyでは、Dockerなどでローカル用のPostgresを立ててlocalConnectionStringに指定し、Hyperdriveに関わる部分の開発・検証だけwrangler devで行う、という運用にしています。SvelteKit側の通常の開発は引き続きVite(bun dev)で進められるため、開発体験を大きく落とさずに済んでいます。