sell整合實戰
database

用 Hyperdrive 讓 Worker 連既有的 Postgres

你已經有一個 Postgres,Hyperdrive 讓 Workers 連它又快又穩——完全不用搬家。

60s預設快取時間
0資料庫搬遷
Pooling連線重複利用
Free免費方案可用
insights

我們要串什麼?

你已經有一個區域型 Postgres 在跑——可能在 Neon、Supabase、AWS RDS,或你自己的伺服器上。它只住在一個地方。但你的 Workers 卻跑在數百個城市裡。這篇教學會用 Hyperdrive 把 Worker 接到那個資料庫,讓每個請求都能重複利用已經接通的連線、並從快取讀資料,而不是每次都付完整的延遲成本。

Hyperdrive 夾在中間,同時扮演「連線池(connection pooler,把連線存起來共用的中介)」和「查詢快取(query cache,把查詢結果記起來)」。你的程式碼照樣用一般的 Postgres 驅動程式——唯一的差別是它連到的是 env.HYPERDRIVE.connectionString,而不是資料庫真正的網址。

schema多個 Worker 呼叫共用一個連線池

快取命中直接回傳

Worker 呼叫 1

Hyperdrive

Worker 呼叫 2

Worker 呼叫 3

連線池:共用的熱連線

查詢快取:記住熱門 SELECT

你既有的 Postgres

fast_forward

把它想成…

資料庫門口的一排待客計程車。與其每個 Worker 都重新叫一台新車、再等它開過來(重開一條連線),Hyperdrive 直接在路邊備好幾台發動中的車,還記得熱門目的地——所以大多數乘客上車就走。

account_tree

各層負責什麼?

dns

你的 Worker

跑遍全球、保持無狀態。它對 env.HYPERDRIVE.connectionString 開一個客戶端,然後執行 SQL。

hub

Hyperdrive

擋在資料庫前面的連線池+快取層。重複利用連線、並回傳已快取的讀取結果。

database

你的 Postgres

依然是唯一的真實來源。資料表結構、資料、供應商通通維持原樣。

vpn_key

連線字串

存放在 Hyperdrive 設定裡,而不是 Worker 程式碼裡——資料庫密碼不會被打包進程式。

schema一筆查詢怎麼被處理

可以且已快取

不可或尚未快取

Worker 收到請求

這筆查詢可以快取嗎?

直接從快取回傳

向連線池借一條熱連線

Postgres 執行查詢

回傳資料列並寫入快取

回應使用者

help

為什麼不直接連資料庫?

從遠方的 Worker 直接連線,每一次都要付 TCP + TLS + 身分驗證的握手成本,而且無伺服器(serverless)的大量呼叫很快就會把資料庫的連線數上限用光。連線池讓你重複利用熱連線;快取則讓重複的讀取查詢完全省掉那趟來回。

swap_vert

沒有 vs 有 Hyperdrive

下面這張圖把同一份工作畫了兩次。上半部直接連線、每次請求都重建一條連線;下半部走 Hyperdrive,重複利用已接通、進到連線池的連線——常常直接從快取回答。

schema連線生命週期比較
"Postgres""Hyperdrive""Worker""使用者""Postgres""Hyperdrive""Worker""使用者"沒有 Hyperdrive - 每次都重開連線(慢)有 Hyperdrive - 連線池 + 快取(快)請求 A建立新連線 + TLS 握手連線就緒SELECT 查詢資料列回應(較慢)請求 B用熱連線池查詢快取命中或共用連線回應(較快)
speed

時間都花在哪

在一條全新的直接連線上,光是握手就可能花掉好幾趟來回,資料都還沒開始傳。Hyperdrive 把這個成本只付一次,再分攤給大量的請求共用。

construction

動手串起來

五個步驟:建立一個指向你資料庫的 Hyperdrive 設定、把綁定加進 wrangler.toml、安裝 Postgres 驅動程式、透過 env.HYPERDRIVE.connectionString 查詢,然後部署。

  1. 建立 Hyperdrive 設定

    把你既有的連線字串交給 Hyperdrive。Wrangler 會印出一組 id——複製起來下一步要用。

    bash
    npx wrangler hyperdrive create my-postgres \
      --connection-string="postgres://user:password@db.example.com:5432/appdb"
  2. 加入 [[hyperdrive]] 綁定

    把 id 貼進 wrangler.toml。一定要開 nodejs_compat 旗標,因為 Postgres 驅動程式會用到 Node 的 API。

    toml
    name = "my-worker"
    main = "src/index.js"
    compatibility_date = "2024-09-23"
    compatibility_flags = ["nodejs_compat"]
    
    [[hyperdrive]]
    binding = "HYPERDRIVE"
    id = "<paste-the-id-from-step-1>"
  3. 安裝 Postgres 驅動程式

    這裡用 postgres.js;node-postgres 的 pg 套件也可以。

    bash
    npm i postgres
  4. 透過 Hyperdrive 查詢

    連到 env.HYPERDRIVE.connectionString——絕對不是資料庫真正的網址。每個 isolate 維持一個小連線池,並在背景關閉它。

    js
    import postgres from "postgres";
    
    export default {
      async fetch(request, env, ctx) {
        // Connect to Hyperdrive, not the database directly
        const sql = postgres(env.HYPERDRIVE.connectionString, {
          max: 5,            // small pool per Worker isolate
          fetch_types: false // skip an extra round-trip
        });
    
        try {
          const products = await sql`SELECT id, name, price FROM products LIMIT 10`;
          // Close in the background so it does not delay the response
          ctx.waitUntil(sql.end());
          return Response.json(products);
        } catch (err) {
          console.error(err);
          return Response.json({ error: String(err) }, { status: 500 });
        }
      }
    };
  5. 部署上線

    發布 Worker。查詢就會走上有連線池、有快取的快速通道了。

    bash
    npx wrangler deploy

安全地讀取與寫入

jsqueries.js
// Parameterized values are sent separately, never string-concatenated
const id = 42;
const rows = await sql`SELECT id, name FROM products WHERE id = ${id}`;

// Writes (INSERT/UPDATE/DELETE) are never cached — they always hit Postgres
await sql`INSERT INTO views (product_id) VALUES (${id})`;
key

別把真實網址寫進程式碼

資料庫密碼只存在你第一步建立的 Hyperdrive 設定裡。一律透過 env.HYPERDRIVE.connectionString 連線,這樣機密就不會跑進你的原始碼或打包檔裡。

school

重點概念

link

連線字串

包含主機、連接埠、帳號、密碼與資料庫名稱的那串 URL。Hyperdrive 把你的藏在 env.HYPERDRIVE.connectionString 後面。

pool

連線池

一組已接通、隨時可用的連線,在請求之間共用,沒人需要重複付建立連線的成本。

cached

查詢快取

可快取的 SELECT 結果會被記住(預設 60 秒),一模一樣的重複查詢就能跳過資料庫。

hourglass_empty

建立連線延遲

一條全新連線在能跑查詢之前,必須先完成 TCP + TLS + 驗證的握手。連線池讓這個成本只付一次。

block

連線數上限

每個 Postgres 都有連線數上限。爆量的無伺服器流量很容易把它用光——連線池讓用量維持平穩。

verified

資料庫仍是來源

Hyperdrive 只負責加速存取。你真正的資料永遠存放在你自己的 Postgres 裡。

tips_and_updates

小提示與陷阱

tune

依新鮮度調整快取

快取預設開啟、最長保留 60 秒(可調到最多 1 小時)。如果某些資料一定要即時,可以用 npx wrangler hyperdrive update <id> --caching-disabled true 關掉它。

  • 沒有 compatibility_flags = ["nodejs_compat"] 和夠新的 compatibility_date,Postgres 驅動程式會載入失敗。
  • 只有唯讀的 SELECT 會被快取;INSERT/UPDATE/DELETE 一定會到 Postgres。
  • 用到 NOW()、RANDOM()、CURRENT_DATE 的查詢會被視為不可快取——甚至只在 SQL 註解裡提到這些函式名稱,也會讓那筆查詢不快取。
  • 一律用 ctx.waitUntil(sql.end()) 收尾,清理才不會拖慢回應。
  • 每個 isolate 的連線池維持小一點(例如 max: 5);Hyperdrive 反正會在背後多工共用。
  • 支援 Postgres 與相容資料庫(Neon、Supabase、RDS、CockroachDB、Timescale)——也支援 MySQL。
  • 想要 Cloudflare 原生的 SQL 資料庫、而不是自備?可以看看 D1。