Workers 定價與限制:CPU time 計費與省錢技巧 | Cloudflare 完整教學

2026/08/04
Workers 定價與限制:CPU time 計費與省錢技巧 | Cloudflare 完整教學

Cloudflare Workers 的執行模型看懂了,接下來就要把它換算成兩件實際的事:要付多少錢、能做到哪裡為止。 這一篇我們把 Free 與 Paid 方案的請求數、CPU 時間、記憶體、bundle 大小、子請求數每一條線畫清楚,解釋 CPU time 計費為何只算運算、不算等待,並教你怎麼估成本、怎麼避開超限。

前言

上一篇《V8 Isolates 執行模型》我們掀開了引擎蓋,看懂 Workers 為何近乎零冷啟動、為何按 CPU 時間計費、為何模組層變數不可靠。文章最後我留了一句話:看懂了執行模型,下一步就是把「限制」量化。 這一篇就是來兌現的。

先給一句話定義:Workers 的定價與限制,本質上是把「你能用掉多少運算資源、用多快」明碼標價與畫線的一套規則。 它包含兩個計費維度(請求次數、CPU 時間)與一組硬性平台限制(每次請求的 CPU 上限、單一 Isolate 的 128MB 記憶體、bundle 大小、子請求數等)。理解這套規則,你才能判斷一個架構在 Workers 上跑起來要花多少錢、會不會撞牆。

打個比方:Workers 的計費像是「按碼表計程車費,但只在司機真正踩油門時跳表」。 傳統 Serverless(如 AWS Lambda)是上車就開始跳表,即使塞在紅燈前等資料庫回應也照跳;Workers 則是紅燈等待(等待 KV、D1、外部 API 的 I/O)不跳表,只有引擎真的在動(跑 JavaScript)才計費。至於平台限制,就像這台車有明確的載重上限與單趟里程上限——超過了不是加錢就能解決,而是得換車(換架構)。

讀完本篇,你會掌握:

  • Free 與 Paid 方案的完整對照——請求數、CPU 時間、程式碼大小、子請求數,每一條線的具體數字與差異
  • CPU time 計費模型——為什麼只算運算不算等待,這對成本估算的實際意義
  • 一套可操作的成本估算方法——從流量與 CPU 時間反推月費,判斷 $5 夠不夠
  • 常見的三個計費/限制陷阱——誤以為按牆上時鐘計費、撞到 CPU 上限、bundle 過大部署失敗,以及對應解法
  • 限制如何反過來影響你的架構決策——哪些工作根本不該放上 Workers

核心概念

兩個計費維度:請求次數 + CPU 時間

先建立最重要的心智模型:Workers 的帳單只由兩個東西構成——你收了多少次請求、這些請求總共燒了多少 CPU 時間。 沒有出口頻寬費、沒有依實例數或記憶體大小計時的費用。這和多數雲端 Serverless 的計費結構明顯不同。

  • 請求次數(Requests):每一次進入 Worker 的 HTTP 請求、每一次 Cron 觸發、每一則 Queue 訊息,都算一次。
  • CPU 時間(CPU Time):所有請求中,實際執行 JavaScript 的毫秒數總和。關鍵是「CPU 時間」不等於「請求耗時」——這是下一節的重點。

Free vs Paid:把每一條線畫清楚

下面這張表是本篇的核心。它把 Free 與 Paid 方案在計費與限制上的差異一次攤開:

項目Free(免費)Paid(每月 $5 起)
請求次數10 萬次 / 天1,000 萬次 / 月(含),超出約 $0.30 / 百萬次
CPU 時間額度隨方案內含3,000 萬 CPU-ms / 月(含),超出約 $0.02 / 百萬 CPU-ms
每次請求 CPU 上限10ms預設 30 秒,最高可設定 5 分鐘
記憶體 / Isolate128 MB128 MB
程式碼大小(壓縮後)3 MB10 MB
外部子請求(fetch)/ 請求5010,000
頂層初始化時間1 秒1 秒
出口頻寬費用(egress)

幾個一定要注意的重點:

  1. 請求額度的計費週期不同:Free 是「每天」10 萬次,跨過午夜重置;Paid 是「每月」1,000 萬次額度。
  2. 最大差異在 CPU 上限:Free 每次請求只有 10ms CPU,Paid 直接跳到預設 30 秒。這 3,000 倍的落差,往往是你決定升級與否的真正原因。
  3. 記憶體兩個方案都是 128 MB:升級 Paid 不會給你更多記憶體。128MB 是 Isolate 模型的硬限制,跟你付不付錢無關。
  4. 沒有出口費用:回傳一個 500MB 的 R2 檔案、串流大量資料,都不額外收頻寬費。這是 Workers 相對某些雲平台很甜的一點。

說明:上表的金額($0.30 / 百萬次、$0.02 / 百萬 CPU-ms 等)是概略值,Cloudflare 會隨時間調整,實際請以官方定價頁為準。本篇重點是讓你抓住「計費結構」與「量級」,而非背誦精確到分的數字。

CPU time 計費:只算運算,不算等待

這是整篇最重要、也最容易被誤解的一節。Workers 按 CPU 時間計費,而 CPU 時間指的是「V8 實際執行你的 JavaScript」的時間,不包含等待 I/O 的時間。

回想上一篇談的 Isolate 執行模型:Worker 是單執行緒事件迴圈,當你 await 一個 KV 讀取、D1 查詢或外部 fetch 時,事件迴圈會讓出控制權去處理別的事,你的程式碼在那段期間根本沒佔用 CPU。Cloudflare 精準掌握每個 Isolate 真正消耗 CPU 的時間,於是只對這段收費。

用一個具體的請求耗時分解來看,最直觀:

一個請求的耗時分解範例:
總耗時(Wall Clock,牆上時鐘):450ms
  ├─ JavaScript 實際執行(CPU Time):8ms    ← 只有這 8ms 計費
  ├─ 等待 KV 回應:120ms                     ← 不計費
  ├─ 等待外部 API:280ms                     ← 不計費
  └─ 等待 D1 查詢:42ms                      ← 不計費

同一個請求,若拿去 AWS Lambda 按牆上時鐘計費,你要付整整 450ms;在 Workers 上你只付 8ms。對 API、BFF、反向代理這類「大部分時間都在等 I/O」的工作負載,實際帳單往往遠低於用總耗時換算的直覺值。

這也解釋了為什麼 Free 方案「每次請求 10ms CPU」聽起來很小、實際卻很夠用:因為 10ms 指的是純運算時間,而不是請求總時長。根據 Cloudflare 官方資料,典型 Worker 的平均 CPU 時間約落在 2ms 出頭,一個純路由 + 快取查詢的 API 請求很難吃滿 10ms。真正會撞到上限的,是把重運算(影像處理、大量加解密、複雜迴圈)塞進單一請求的場景。

三個關鍵術語

  • CPU 時間(CPU Time):V8 實際執行 JavaScript 的毫秒數,不含等待 I/O。計費與每次請求上限都以它為準。
  • 牆上時鐘時間(Wall Clock Time):請求從進入到回應送出的總耗時,含所有 I/O 等待。Workers 用它計費,理解這點能省下大量誤判。
  • 子請求(Subrequest):Worker 內部發出的每一次外部 fetch(),以及對 KV、R2、Cache API 的 I/O 操作,都算一次子請求。每次請求有數量上限(Free 外部 fetch 50 次、Paid 1 萬次)。

實作範例

概念聊完,我們把「量測 CPU 時間」與「估算成本」變成可操作的東西。

在程式碼裡觀察運算與等待的差別

Workers 的 CPU 時間不能靠 Date.now() 直接量(因為 Date.now() 量到的是牆上時鐘,含等待)。但我們可以用一段刻意設計的程式碼,把「純運算耗時」和「含等待的總耗時」並排印出來,親眼看見兩者的落差:

// src/index.ts
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    // ① 量測一段「純運算」的牆上時鐘耗時(無 await,近似 CPU 時間)
    const cpuStart = Date.now();
    let sum = 0;
    for (let i = 0; i < 1_000_000; i++) sum += i; // 純運算,會佔用 CPU
    const cpuMs = Date.now() - cpuStart;

    // ② 量測一段「含 I/O 等待」的牆上時鐘耗時
    const wallStart = Date.now();
    await fetch("https://example.com"); // 等待外部回應,這段不算 CPU 時間
    const wallMs = Date.now() - wallStart;

    const data = {
      note: "純運算耗時近似 CPU 時間;含 I/O 的耗時是牆上時鐘時間",
      cpuLikeMs: cpuMs,   // 這段運算才是計費依據
      wallWithIoMs: wallMs, // 這段大多在等待,不計 CPU 費用
    };
    return new Response(JSON.stringify(data, null, 2), {
      headers: { "Content-Type": "application/json; charset=utf-8" },
    });
  },
} satisfies ExportedHandler<Env>;

要看真正精準的 CPU 時間,別靠土法煉鋼。正式做法是在 wrangler.jsonc 開啟 observability,然後到 Cloudflare Dashboard 的 Workers 分析頁,或用 wrangler tail 串流即時日誌,觀察每個請求實際回報的 CPU 時間分佈。tail 事件的 outcome 欄位也會在超限時回報 exceededCpu,是排查超限最直接的訊號。

在 wrangler.jsonc 調整 CPU 上限

Paid 方案下,若你確實需要單一請求跑超過預設 30 秒的運算,可以在設定檔提高上限(最高 5 分鐘):

{
  "name": "my-worker",
  "main": "src/index.ts",
  "compatibility_date": "2026-08-01",

  // 提高每次請求的 CPU 時間上限(單位:毫秒)
  "limits": {
    "cpu_ms": 60000  // 60 秒;最大可設 300000(5 分鐘)
  },

  // 開啟可觀測性,才能在 Dashboard 看到 CPU 時間分佈
  "observability": {
    "enabled": true,
    "head_sampling_rate": 0.1
  }
}

注意:調高 cpu_ms 不會讓你的程式跑更快,只是允許它跑更久不被中斷。 而跑越久、CPU 時間累積越多,帳單也越高。這個設定是給「確實需要長運算」的場景用的安全閥,不是效能開關。

一套可操作的成本估算方法

很多人卡在「到底要不要升級 Paid」。其實只要三個數字就能估:月請求數、每次請求平均 CPU 時間、Free 額度。 我們用一個假想的 API 服務來走一遍:

假設一個 API 服務:
- 每天請求數:20 萬次   → 每月約 600 萬次
- 每次請求平均 CPU 時間:3ms

一、先看 Free 夠不夠:
   Free 上限 = 10 萬次 / 天
   實際 20 萬次 / 天 > 10 萬  → 超過,必須用 Paid

二、算 Paid 是否在 $5 內含額度:
   請求:每月 600 萬次   < 內含 1,000 萬次   → 不超
   CPU 時間:600 萬次 × 3ms = 1,800 萬 CPU-ms
             1,800 萬       < 內含 3,000 萬   → 不超

三、結論:兩個維度都在 $5 內含額度內
   → 每月費用 = $5(最低月費,額度沒用完也是 $5)

估算的訣竅在於:先用請求數與平均 CPU 時間,分別檢查是否超過內含額度;兩者都不超,就是最低月費。 只要有一個維度超出,再把超出部分乘上對應單價加上去即可。真正該擔心的往往不是超額費用(Workers 單價很低),而是單次請求撞到 CPU 上限——那不是花錢能解決的,得靠架構調整,正是下一節的主題。

常見錯誤與最佳實踐

坑一:誤以為 Workers 按「牆上時鐘時間」計費,結果高估成本、做錯技術選型。

這是最常見的誤解。很多人看到「我的請求要 400ms 才回應」就以為很貴,於是放棄 Workers 選了別的方案。實際上那 400ms 裡可能有 390ms 在等資料庫和外部 API,真正計費的 CPU 時間只有 10ms 上下。正確做法:估算成本時只算「純運算」時間,把大量 I/O 用 Promise.all() 並行化——並行不但降低牆上時鐘延遲,也因為 I/O 等待不計費,完全不會增加 CPU 帳單。理解這點,你會發現 Workers 對 I/O 密集工作負載的性價比高得驚人。

坑二:把重運算塞進單一請求,撞到 CPU 時間上限。

Free 方案每次請求只有 10ms CPU,即使 Paid 預設也「只有」30 秒。當你在單一請求裡做影像轉檔、大量密碼學運算、或跑一個沒讓出控制權的緊密迴圈,就可能觸發 Too much CPU time usedtail 事件回報 exceededCpu)。正確做法有幾種:把非關鍵運算用 ctx.waitUntil() 移到回應送出後的背景執行;把重任務拆成 Queues 訊息,由多個 Worker 分批消化;需要真正長時間運算(影片轉碼、ML 訓練)時,這根本不該放 Worker——改用 Cloudflare Workflows 編排、搭配 Containers 跑長運算。限制在告訴你什麼工作適合這個平台,硬撐只會事倍功半。

坑三:bundle(程式碼)過大,部署直接失敗。

Worker 的程式碼壓縮後有大小上限(Free 3 MB、Paid 10 MB)。當你不小心 import 了一整包肥大的 npm 套件、或把大型 JSON 資料、字型、圖片打進 bundle,就可能超標導致部署失敗。正確做法:用 wrangler deploy --dry-run 在部署前先檢查產物大小;把靜態資源(圖片、字型、大型資料)放到 R2 或 Assets Binding,而不是打進程式碼;優先選用為邊緣環境設計的輕量套件(例如用 Hono 而非搬整套 Express 生態);善用 tree-shaking,只 import 真正用到的函式。另外別忘了頂層初始化有 1 秒上限,別在模組頂層做重計算或網路請求,否則冷啟動會拖慢甚至部署失敗。

額外提醒:子請求數也是一條線。 Free 每次請求最多 50 個外部 fetch,Paid 是 1 萬。如果你在一個請求裡對外打了幾十上百次 API,很容易撞牆。正確做法:用 Promise.all() 並行、合併多個呼叫為批次請求、加一層 KV 快取減少重複外部請求。

小結

上一篇《V8 Isolates 執行模型》我們把 Workers 的執行核心講透——為何近乎零冷啟動、為何按 CPU 時間計費、為何模組層變數不可靠。這一篇,我們把那套模型換算成了真實的錢與邊界:

  • Workers 只有兩個計費維度:請求次數 + CPU 時間,沒有出口頻寬費。
  • CPU time 計費只算運算、不算等待——等 KV、D1、外部 fetch 的 I/O 空檔完全不計費,這讓 I/O 密集工作負載的實際帳單遠低於直覺。
  • Free 與 Paid 的最大差異在 CPU 上限:Free 每次請求 10ms、Paid 預設 30 秒(最高 5 分鐘);記憶體則固定 128MB,付錢也不會變多。
  • 成本估算三步驟:用月請求數與平均 CPU 時間,分別檢查是否超過內含額度,兩者不超就是最低月費 $5。
  • 限制會反過來定義架構:撞到 CPU 上限、bundle 過大不是花錢能解決的,而是提醒你這個工作是否適合放上 Workers——重運算交給 Queues / Workflows / Containers,大型資產交給 R2。

到這裡,我們完成了 Workers 的第一組核心 fundamentals:從邊緣運算概念、第一個 Worker、V8 Isolates 執行模型,到本篇的定價與限制。你現在不只知道 Workers 怎麼跑,也知道它跑起來要多少錢、能跑到哪裡為止。

接下來,我們要把鏡頭拉近到 Worker 每天處理的最基本物件。下一篇《Request 與 Response》,我們會深入 fetch handler 最核心的兩個角色——請求進來長什麼樣、回應怎麼構造、Headers 與 Body 如何操作,以及串流回應如何和本篇的 128MB 記憶體限制產生關聯。運算核心的基礎打完了,該來認識資料本身了。

想深入官方定價細節,可以隨時參考 Cloudflare 官方 Workers 定價文件平台限制文件。準備好認識 Request 與 Response 了嗎?我們下一篇見。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。

本週主打

AI 自動化入門包

你每天手動在做的那些煩事,其實 AI 可以自己跑。這份給你 10 個照著做就會的自動化工作流 + 50 個複製即用的提示詞,不用會寫程式。

看看這個產品 →