事故調查 · VIBE CODING 的雲端帳單 · 2026-10

每加一分,
就扣一分

一位國小老師用 AI 做了一個「加分」工具,每月 5.4 萬人在用,雲端帳單一個月 NT$2,854。他的產品機制是加分,但每加一個功能、技術選型就錯一項,帳單上就扣一分。這份報告用同一張計分板,把加分和扣分並排看。

案例:方方老師「FunClass 翻課星球」· 依據:公開網頁、前端程式、GitHub 公開 repo、作者貼文、帳單截圖 · 未登入、未碰雲端資料

TL;DR

三句話

  1. 錢不是 Cloudflare 收的。workers.dev 只負責送網頁;NT$2,854 幾乎全是 Firebase Realtime Database 的下載流量。
  2. 扣分的那一步只有一個:把「整班壓成一塊」的備份格式,直接拿來當即時廣播的格式。老師加一分,全班 30 台裝置各自重新下載整塊。按位元組計費的資料庫,這樣做大約貴 400 倍。
  3. 最短的修法不用搬家:多開一個只放即時數字的小節點給學生端監聽,整塊改成開艙讀一次。估計下載量從每天 1.2 GB 降到 0.1–0.3 GB,回到免費額度內。
繳費通知 · 第二聯(存根)超出免費額度
專案classhubgame
方案Firebase Blaze(隨用隨付)
帳單期間2026-09-01 – 09-30
專案費用NT$2,854

月活躍使用者(含匿名)

5.4 萬

9 月一路線性上升

單日活躍最高

4,052

週末掉到 1,200 左右

RTDB 單日下載

1.2 GB

免費額度約 360 MB/日

Firestore 讀取/日

34

不到免費額度 0.1%

01 · 計分板

加分欄和扣分欄,同一張表

左欄是作者做對的事,右欄是同一個時期做錯的技術決定。每一列都是一個功能被加進來的時刻。這張表就是整份報告的主軸,後面的章節只是把每一列攤開。

時間+1 · 做對的-1 · 選錯的淨分
2025-10先做出老師自己要用的加分工具,資料正規化存進 Firestore。—+1
2026-05資料改為本機優先,雲端只當備份;整班壓成一份文件、每天限存 3 次。按次計費的 Firestore 這樣做很省。—+1
2026-05加學生遊戲艙:掃 QR 進艙,加分變代幣,寵物、轉蛋、Boss 戰。使用者從老師變成全班。同步層改用按位元組計費的 Realtime Database,卻沿用整班壓縮塊,每台學生裝置常駐監聽整塊。−1
2026-05所有學生操作走 Cloud Functions 判定,防作弊。每個操作都多一次函式呼叫和一次資料庫往返;學生每台用匿名登入,月活躍衝到 5.4 萬。0
2026 夏發現一天燒 300 多元,做了底層改造;分數加緩衝、寫入加冷卻、內容沒變不重發。修的是「發布頻率」,沒有修「每次發布的大小」。0
2026-09自己找到「拆開存」的方向,開始試行。只對一個帳號開放;正式環境仍是整塊廣播。0
全程工具完全免費、不鎖功能、伺服器費自付。贊助收入連一週伺服器費都不夠;寫給 AI 的技能規定「新手沒問成本就不教定價」,所以沒人在選型時問過單位成本。−1

功能一直在加分,架構一直在扣分。產品的加分機制設計得很好;少的是一個會在每次選型時扣分的機制。

02 · 現況架構

三張圖看懂錢從哪裡流出去

C4 模型由外往內三層:L0 是誰在用、依賴哪些外部服務;L1 是系統由哪幾個部分組成;L2 是一次加分在程式裡經過哪些元件。藍色粗線是花錢的那條路。

L0 · 系統情境

老師管理班級,學生用自己的裝置進遊戲艙;FunClass 只依賴三個外部服務。

老師 Google 帳號登入 學生(每班約 30 人) 掃 QR、匿名登入 FunClass 翻課星球 班級工作台+學生遊戲艙 Google 帳號 老師登入 QR 圖片服務 api.qrserver.com unpkg CDN React 18 建班、加分 養寵物、看排行
虛線框是外部服務。網址雖然掛在 workers.dev,但在這一層看不到 Cloudflare:它只是把網頁送出去的地方,不是後端。

L1 · 容器

後端幾乎都在 Firebase。老師把整班壓縮塊寫進 Realtime Database,每台學生裝置各自監聽同一塊。

老師工作台(瀏覽器) React 18 · IndexedDB 資料先存本機 學生遊戲艙(瀏覽器) 每台各自連線 一班約 30 台 Cloudflare Worker 只送網頁與圖檔 Firebase · classhubgame Auth Google+匿名 Realtime Database classPublic/{班級} =整班壓縮塊 Cloud Functions 18 個 callable Firestore 舊版與每日備份 分數一變就重寫整塊 onValue:整塊 × 30 台 抽蛋、戰鬥、簽到 讀寫學生狀態
Firestore 一天只被讀 34 次,可以忽略;Auth 給老師和學生登入用。帳單幾乎都落在中間那個藍框的下載流量。

L2 · 元件:一次「7 號 +1 分」走過的路

分數有緩衝、內容沒變不會重新發布,這些都做對了;但只要有變,送出去的就是整塊。

加分按鈕 老師端 分數緩衝 合併連續點擊 壓縮+指紋 整班 → gzip classPublic 整塊(示意 40 KB) 學生艙 × 30 解壓整塊再畫 指紋相同才跳過;寫入冷卻 5 秒 每台各下載一次整塊 一次加分 ≈ 40 KB × 30 台 ≈ 1.2 MB(示意)
元件名稱對應線上程式:teacher-score-buffer、class-document-codec、firebase-cloud 的發布函式。在手機上,圖可以左右捲動。

03 · 扣分的那一步

同一招,換了計費單位就從省錢變燒錢

兩個資料庫的計費方式不同,決定了同一個技巧的命運:

一次「7 號 +1 分」送出的資料× 監聽裝置總下載
整班壓縮塊(現況)classPublic/{classId}約 40 KB30約 1.2 MB
拆成每人一個節點students/07/score約 100 B30約 3 KB

整塊大小是假設值,線上實際大小沒辦法在未登入時量到。但帳單上的 1.2 GB/日反推,約等於每天重新下載整塊 3 萬次;以每天 3,000 多位學生算,每人約 10 次,大致就是「開艙一次,加上班上每次有人加分」。

AI 為什麼沒提醒他

作者寫給 Codex 的技能 build-firebase-cloudflare-app 有一條:使用者是新手、沒提到成本時,選不用付費的路線,而且不要教定價。本意是不嚇跑新手,結果是 agent 選資料庫、設計同步格式時,沒有人回頭問「每多一位學生要多付多少」。agent 預設優先讓功能動起來;單位成本不在它會檢查的項目裡。

04 · 把分加回來

先走最短的路:A1 冷熱分離

不動資料模型,整塊壓縮資料照舊,只把「需要即時跳動的數字」抽出來另外走一條小路:

  1. 新增小節點 classLive/{班級}:只放每人的能力值和代幣,一般 JSON,不壓縮。老師加分時順手更新這一格。RTDB 只會把變動的那一格推給監聽者。
  2. 學生艙改監聽 classLive;整塊改成開艙時 get() 讀一次,不再常駐監聽。
  3. 整塊加版本號:學生端把整塊留在本機,開艙時先比對版本,有變才下載。他已經有 classPublicMeta 這個節點了。
  4. 整塊的發布改成節流:名單或設定改了、每隔幾分鐘、或老師按「下課」時才發布。

現況 vs A1:差別只在藍色那條路

A1 多了一個小節點,學生端從「常駐監聽整塊」改成「監聽小節點、開艙才讀整塊」。

現況 加分 分數緩衝 壓縮整班 classPublic 整塊 學生艙 × 30 每次加分:整塊 × 30 A1 加分 分數緩衝 classLive(新增) { s07: 111 } 一般 JSON 壓縮整班 節流後才發布 classPublic 整塊 附版本號 學生艙 × 30 只推差異 ~100 B × 30 開艙時 get() 版本變了才讀
老師端多一次寫入(一格數字),學生端換一個監聽路徑,整塊發布加一個計時器。資料格式、備份、Cloud Functions 都不用動。
現況A1(估算)
每次加分推送的資料整塊 × 30 台一格(約 100 B)× 30 台
整塊被下載的時機開艙+每次分數變動只有開艙,而且版本變了才下載
RTDB 下載量/日1.2 GB(帳單實測)約 0.1–0.3 GB
對照免費額度(約 360 MB/日)超出約 3 倍落在額度內
改動範圍—多 1 個寫入、換 1 個監聽、加 1 個節流計時器;不搬資料

其他四條路

做法怎麼做放棄什麼估計月費
A · 全面拆資料留在 Firebase每位學生一個節點、排行榜一個節點,學生只監聽自己的和排行榜。接近他正在試行的 split-storage,但要改整個資料模型和既有資料。幾乎不用放棄什麼NT$0–300
B · Firestore 小文件按次計費每人一份文件、排行榜一份,onSnapshot 只掛這兩個。每次變動算 30 次讀取,跟大小無關;估每天約 60 萬次,超過免費 5 萬次。要重寫同步層約 NT$200–350
C · Cloudflare Durable Objects一班一個房間每班一個 DO,WebSocket 加 hibernation 推差異;狀態存 DO 的 SQLite,備份進 D1,寵物圖當靜態檔。流出流量不收費。免費方案就能跑,但超過額度會直接報錯,上課中斷比多付錢糟;建議付每月 US$5 換掉硬上限。重寫後端;登入改房間代碼加簽章 tokenNT$0 或 US$5 起
D · 不做即時學生艙開啟時讀一次自己的資料,不常駐監聽;排行榜由老師在教室投影。學生裝置上的即時跳分NT$0

只能做一件事就做 A1。規模再大一個數量級,或想讓費用完全不隨人數成長,再考慮 C。

05 · 鎚子與釘子

換到 Cloudflare 不是重點,別只有一把鎚子才是

這份報告前面算了 Cloudflare 的帳,很容易讀成「Firebase 不好,搬去 Cloudflare 就對了」。這個結論是錯的,而且錯的方式跟作者當初一樣。

作者的技能裡寫死了一條預設路線:點子進來,Firebase 當後端,Cloudflare 送前端。所以不管加什麼功能,答案都是 Firebase。遊戲艙需要即時同步,Firebase 有 Realtime Database,就用它;格式是現成的壓縮塊,就沿用。每一步都是「手上有什麼就用什麼」,沒有一步是「這個問題的計費單位是什麼」。如果他當初的鎚子是 Cloudflare,一樣會有另一種釘子:Durable Object 忘了 hibernation,掛一整天的房間照樣能燒掉上百美元。

所以綁定本身不是問題。Firebase 的 SDK 綁得很深,Durable Objects 的程式模型也綁得很深,兩邊換過去都是重寫。該省思的是另一件事:

回到計分板:每加一個功能,就有一次選型。選型沒有扣分機制,最後扣的就是帳單。

06 · 變現

先把成本降到零,再談收入

作者說過,訂閱和贊助的收入連一週伺服器費都付不起。一個月 NT$2,854 靠小額贊助本來就很難打平;先把成本壓到每月 US$5 以下,用愛發電才撐得住,之後的收入才是收入。

方式怎麼做門檻與風險
1 · 老師端 freemium本機版永久免費;真正花雲端錢的學生遊戲艙改成付費或限班級數。例如每年 NT$990,300 位老師付費約 NT$30 萬/年。付費功能得是老師離不開的那一塊;要有個人可申請的金流。
2 · 學校與縣市授權縣市用「推動中小學數位學習精進方案」經費統一採購教學軟體;屏東縣 114 年度清單就有 PaGamO、加分吧、LoiLoNote。也可申請上架教育部「校園數位內容與教學軟體」選購平台。要成立公司或工作室,並符合未成年學生的個資與資安要求。門檻最高,金額也最大。
3 · 研習與課程作者已有「FunFun.AI」品牌和公開的 Codex 技能,適合開「老師用 AI 做工具」的研習。這張帳單本身就是教材。收入跟著作者的時間走,但最快能開始。
4 · 出版社或平台合作授權給教科書出版社或既有班級經營平台。Classcraft 在 2023 年被 HMH 收購,2024 年 6 月原版停止服務。合約要寫清楚原產品是否繼續維運。
5 · 家長端加值參考 ClassDojo:老師學生免費,家長訂閱 ClassDojo Plus(每月 US$4.99),學校另買授權。台灣家長付費加上轉蛋機制容易引發爭議,排最後。

不建議的方向

不要讓學生花錢買轉蛋、寵物或道具,也不要放廣告。使用者是小學生,學校和家長的反彈會大於收入;一旦被教育局列為不宜使用,免費用戶也會跟著流失。

07 · 給用 AI 寫工具的人

把扣分機制裝進流程

下次讓 AI 加「即時同步」「多人連線」之前,要求它先回答三個問題,答不出來就不准動手:

  1. 計費單位是什麼?按次、按位元組、按人頭,還是按秒。同一個技巧換了單位,結果可能相反。
  2. 使用者做一個動作,幾台裝置各下載多少?扇出數乘每次資料量,就是帳單成長的速度。
  3. 使用者變成 100 倍,帳單變幾倍?線性成長就要先想誰付錢。

自己寫 agent 技能的人,可以把這三題寫成一道關卡:加入任何即時或多人功能前,agent 必須寫出計費單位、估 10 倍和 100 倍時的月費,再讓使用者決定。這就是作者的加分機制少掉的那一半:功能加一分,選型答不出來就扣一分。

附 · 證據與限制

哪些是看到的,哪些是推的