Cloudflare Workers × Supabase を安全に繋ぐガイド — Hyperdrive編

要約
Cloudflare WorkersからSupabaseに繋ぐならHyperdrive経由が公式推奨。接続プーリング、IPレンジ固定化、クエリキャッシュが全部タダで付いてくる
意見はこのエリアに表示されます

この記事は人間が監修し、AIに書かせました。

⓪ tldr

Cloudflare WorkersからSupabaseに繋ぐならHyperdrive経由が公式推奨。接続プーリング、IPレンジ固定化、クエリキャッシュが全部タダで付いてくる。

構成IP制限プーリングORMコスト推奨度
Workers → Hyperdrive → Direct (5432)⚠️ CF IPレンジで可✅ CF側✅ Drizzle可00〜5/月推奨
Workers → Supavisor (6543)❌ 不可✅ SB側⚠️ prepare:false必須$0△ 代替
Workers → Data API (supabase-js)➖ HTTP➖ 不要❌ ORM不可$0△ 用途限定
Workers → D1➖ 内部➖ 不要✅ Drizzle可$0✅ CF完結向き

最小構成のコスト感:

項目FreePaid ($5/月)
Workers リクエスト10万/日1,000万/月
Hyperdrive クエリ10万/日無制限
Supabase (Free)500MB, 60接続
合計$0/月$5/月

DAU 1,000人規模の個人開発なら $5/月 で安全に運用できる。


先制チェック — 始める前に知っておくべき3つの内容

🚨 致命的欠落

  1. prepare: false を設定しないと全クエリが死ぬ — Hyperdrive/Supavisorはtransaction modeで動作する。prepared statementsは非対応。Drizzleで忘れると Error: prepared statement "s1" already exists で全滅する。
  2. DBクライアントをグローバルスコープで初期化すると本番で死ぬ — Workersはリクエスト間でグローバル変数を共有する。前のリクエストの古い接続を掴んで Connection terminated unexpectedly が間欠的に発生する。
  3. Hyperdrive + Supavisor を重ねると壊れる — 両方ともtransaction modeプーラー。二重にするとprepared statementsの不整合やレイテンシ加算が起きる。HyperdriveにはDirect接続(5432)を渡す。

🏭 業界の常識

  1. SupabaseのDirect接続はデフォルトIPv6 — 2024年1月以降移行済み。Hyperdriveは内部でIPv6対応しているので基本問題ないが、IPv4アドオン($4/月)が必要になるケースもある。
  2. supabase-jsとDrizzle+postgres.jsは全く別の接続経路 — supabase-jsはHTTP(PostgREST経由)、Drizzle+postgres.jsはTCP(PostgreSQLワイヤープロトコル)。セキュリティモデルも制約も違うのに、混同されやすい。
  3. HyperdriveのDBへの送信元はCloudflareの公開IPレンジ — 公式FAQに明記されている。SupabaseのNetwork RestrictionsでこのIPレンジをallowlistに設定すれば、フルオープンを避けられる。

💣 後から気がつくと困るもの

  1. Hyperdrive Free: 10万クエリ/日 — 認証チェック等でリクエストごとに2〜3クエリ走ると、PV 5万/日で上限突破。Workers Paid ($5/月)にすれば無制限。
  2. Supabase Free: 同時接続60本 — Hyperdriveプール上限(Free: ~20, Paid: ~100)との組み合わせに注意。Freeプラン同士なら安全圏。
  3. Hyperdriveのクエリキャッシュはデフォルトで60秒ON — ユーザー固有データが古いまま返る可能性がある。認証系テーブルはキャッシュ無効化が必要。

① 用語解説 — 2歩手前から

接続方式を「道路」に例える

比較表

特性Hyperdrive経由Supavisor経由Data API
プロトコルTCP (Postgres)TCP (Postgres)HTTP (REST)
ポート— (自動)6543443
プーリングあり (CF側)あり (SB側)不要
IP制限⚠️ CF IPレンジ❌ 不可➖ HTTP
ORM (Drizzle)⚠️ prepare:false
RLS任意任意✅ 前提
レイテンシ低い(プール済み)中間中間
CF公式推奨

よくある誤解を先に潰す

誤解1: 「WorkersからPostgreSQLに直接繋げない」
→ 昔は本当だったが、今はTCPソケット対応済み。さらにHyperdriveでプーリングまで面倒見てくれる。

誤解2: 「supabase-jsを使えば全部解決」
→ クライアントサイド向けの設計で、ORM非対応・型安全性が低い・トランザクション不可。サーバーサイドではDrizzle + postgres.jsの方が適している。

誤解3: 「PostgreSQLを使いたいならD1に移行するしかない」
→ D1はSQLite。PostgreSQLの機能(RLS, CTE, JSONB, pg拡張)が必要ならHyperdrive経由でSupabase/Neon等に繋ぐのが正攻法。


② Step by Step — Hyperdrive × Supabase × Drizzle の構築

なぜこの構成なのか

Cloudflare公式ドキュメントが「SupabaseにWorkersから繋ぐならHyperdrive経由」と明示している。理由は3つ:

  1. 接続プーリング — リクエストごとのTCPハンドシェイク(7往復)を省略
  2. IPレンジの固定化 — CloudflareのIPレンジから送信。allowlist設定が可能に
  3. クエリキャッシュ — 同じSELECTを60秒キャッシュしてDB負荷軽減

Step 1: Supabase側の準備

Supabase Dashboard → Project Settings → Database で接続情報を確認:

Step 2: Hyperdrive コンフィグ作成

もしエラーが出たら:

対処: Supabase Dashboard → Add-ons → IPv4 add-on を有効化($4/月)。SupabaseのDirect接続はIPv6がデフォルトなので、IPv4アドオンで解決する。

Step 3: wrangler.jsonc の設定

Step 4: Worker コード(Hono + Drizzle)

🪤 NG vs ✅ 正解の対比


③ 罠カタログ

罠1: prepare: false 忘れ

原因: transaction modeではクエリごとに別の物理接続が割り当てられる可能性がある。prepared statementsはコネクションに紐づくので衝突する。

エラー:

対処:

罠2: トランザクション内で外部API呼び出し

原因: transaction modeではトランザクション中ずっとDB接続を占有。外部API(3秒)を挟むとプールの1本が無駄に使われる。

エラー(接続枯渇時):

対処:

罠3: Hyperdriveキャッシュでデータが古い

原因: デフォルトで全SELECTが60秒キャッシュされる。プロフィール更新直後に古いデータが返る。

対処:

認証系などリアルタイム性が必要なデータ用に、キャッシュ無効のHyperdriveを別途作る:

罠4: Workers の同時外部接続上限

原因: Workersは1リクエストあたり同時6本まで。max: 10 は失敗する。

エラー:

対処:

罠5: nodejs_compat 未設定

原因: postgres.jsがNode.jsの crypto, net, tls を使う。フラグなしだと起動すらしない。

エラー:

対処:


④ 判断基準 — いつ何を選ぶか

フローチャート

規模別の推奨構成

規模DAU構成月額目安
趣味・MVP〜100Workers Free + Hyperdrive Free + Supabase Free$0
個人開発100〜1,000Workers Paid + Hyperdrive + Supabase Free$5
成長期1,000〜10,000Workers Paid + Hyperdrive + Supabase Pro$30
B2B SaaS10,000+Workers Paid + Hyperdrive + Supabase Team$599+

⑤ 内部動作 — Hyperdriveの中で何が起きているか

接続フローの比較

Hyperdriveのプーリングモード

IPレンジの仕組み

Cloudflare公式FAQより:

Hyperdrive connects to your database using Cloudflare's IP address ranges.
You can use this to configure restrictions in your database firewall.

Supabase側の設定: Dashboard → Project Settings → Database → Network Restrictions で、CloudflareのIPレンジをallowlistに追加。


⑥ 構成の選択肢と比較

Supabase vs Neon(Workers接続観点)

観点SupabaseNeon
東京リージョン✅ あり❌ なし(2026/3時点)
Workers接続Hyperdrive推奨@neondatabase/serverless (HTTP)
RLS✅ 標準搭載なし(アプリ側実装)
無料枠500MB, 60接続0.5GB, 無制限コンピュート

東京リージョンが必要ならSupabase。不要ならNeonのHTTP driverも良い選択肢。

Supabase vs D1(Workers接続観点)

観点Supabase (PostgreSQL)D1 (SQLite)
容量上限プラン依存(Free: 500MB)10GB/DB
RLS / CTE / JSONB❌ or 限定的
pg拡張(pgvector等)
書き込み性能高い低い(単一ライター)
移行の自由度高い(他のPG環境へ移行容易)低い(SQLite固有)

DBはアプリより寿命が長い。 PostgreSQLで始めれば、将来Supabaseを卒業しても他のPostgresホスティングにスキーマごと移行できる。

Drizzle + postgres.js vs supabase-js

観点Drizzle + postgres.jssupabase-js
接続TCP (PostgreSQLプロトコル)HTTP (PostgREST)
型安全性✅ スキーマから型生成⚠️ 手動型定義
JOIN / トランザクション❌ or 制限あり
マイグレーション✅ drizzle-kit
Hyperdrive互換❌(HTTP接続なので対象外)

サーバーサイドで使うなら Drizzle。クライアントサイド(ブラウザ/React Native)ならsupabase-js。


⑦ 罠チートシート

#罠名影響度発見タイミング対処
1prepare: false 忘れ🔴 全クエリ死亡初回デプロイpostgres()にprepare: false
2グローバルDB初期化🔴 間欠エラー負荷上昇時ハンドラ内で初期化
3nodejs_compat 未設定🔴 起動不可デプロイ時wrangler.jsonc に追加
4Hyperdrive + Supavisor 二重🔴 接続不安定初回接続Direct (5432) を使う
5max 値が大きすぎる🟡 接続枯渇高負荷時max: 1
6トランザクション内で外部API🟡 プール枯渇高負荷時トランザクション外に移動
7キャッシュでデータが古い🟡 体験劣化更新直後認証系はキャッシュ無効
8IPv6でcode:2015🟡 セットアップ失敗Hyperdrive作成時IPv4アドオン($4/月)
9compatibility_date が古い🟡 互換性問題不定期2024-09-23以降
10postgresユーザーで直接接続🟡 セキュリティ専用ユーザー作成

⑧ 「知らなかったでは済まない」補足

Placement Hints でレイテンシ最小化

Cloudflare FAQによると、Placement設定によりクエリレイテンシが 20-30ms → 1-3ms に改善されるケースがある。Supabaseの東京リージョンと合わせると、エッジ実行でありながらDB近接配置になる。

Better Auth との組み合わせ注意

Better Authを使う場合、Hyperdrive経由で認証が不安定になる既知の問題がある(GitHub Issue #2274)。回避策:

  1. 認証系のみSupavisor (6543)、業務クエリはHyperdrive — 2つの接続先を使い分ける
  2. セッションストレージをKV/D1に逃がす — DB接続を認証から切り離す
  3. 最新バージョンで修正されている可能性もあるため、signIn → session取得 → signOut の最小検証を推奨

Supabase側のNetwork Restrictions設定

Hyperdrive経由でCF IPレンジに限定する手順:

  1. からIPv4/IPv6レンジを取得
  2. Supabase Dashboard → Project Settings → Database → Network Restrictions
  3. CF IPレンジを追加 + 自分の開発環境IPも追加(忘れるとローカル開発で繋がらなくなる)

注意: Network RestrictionsはDirect接続とPooler接続の両方に適用される。ローカルからSupavisor経由で繋ぐ場合も自分のIPが必要。


参考資料

Explore More
関連記事はありません。