TL;DR
ClinCalc + ExClinCalc + Kaizei 三個系統的真實月成本:$0。靠的不是省錢魔法,是針對「免費 tier 邊界」設計架構。本文寫給類似背景的獨立開發者:怎麼做、能撐到哪、什麼情況下需要付費。
我目前的真實帳單
直接攤開來:
| 服務 | 用途 | 免費額度 | 我的用量 | 月費 |
|---|---|---|---|---|
| Cloudflare Pages | 前端託管(3 個專案) | 無限頻寬、500 builds/月 | < 100 builds/月 | $0 |
| Cloudflare Workers | API 後端(3 個 Worker) | 100K req/day | < 5K req/day | $0 |
| Cloudflare KV | rate limit / 簡單快取 | 1GB 儲存、100K 讀/day | 微量 | $0 |
| Cloudflare DNS | 4 個子網域 | 不限 | 4 個 | $0 |
| Supabase 專案 #1 | ClinCalc DB + Auth | 500MB DB、1GB 儲存 | < 50MB | $0 |
| Supabase 專案 #2 | ExClinCalc DB + Auth | 同上 | < 30MB | $0 |
| Supabase 專案 #3 | Kaizei vault | 同上 | < 10MB | $0 |
| GitHub | 程式碼 + Actions | 公開 repo 免費、2000 min Actions | < 200 min/月 | $0 |
| Resend | 認證 email 寄送 | 100 封/day | < 30 封/day | $0 |
| Gemini API | LLM 翻譯 / OCR(ClinCalc) | 限速但有月配額 | 突發 | $0–3 |
| 合計 | $0–3 |
Gemini 是唯一不確定 ── 用量大時會收費,但 ClinCalc 流量低,目前都在免費配額內。
為什麼這個組合可行
關鍵不是「找最便宜的 vendor」,是選免費 tier 邊界跟我的負載特性匹配的服務。
Cloudflare:邊緣免費 tier 對低頻負載友善
免費 tier:100,000 req/day(= ~ 1.16 req/s 平均)
對「個人開發、小規模上線」── 這個額度大到天荒地老。我三個 Worker 加起來目前 < 5,000 req/day,連 5% 都用不到。
關鍵特性:沒有冷啟動懲罰。Lambda 免費 tier 也大方但每次冷啟動付延遲,Workers 沒這問題。
Supabase:每專案 500MB 資料庫對醫療 / 個人應用夠用
免費 tier:500MB DB、1GB storage、50,000 monthly active users
醫療系統的單個診所資料量不大(病人清單 + 病歷 + 處方)。我 ExClinCalc 的測試 DB 有 50 個病人 + 數百筆 SOAP 病歷 + 處方 ── 用了不到 30MB。
關鍵限制:閒置 7 天會被 pause。需要 keepalive(下節說)。
GitHub:公開 repo + Actions 免費
公開 repo 無限 + 2000 分鐘 Actions/月。我的 deploy + keepalive 加起來大概 200 分鐘/月,遠在限額內。
踩到的坑(依嚴重度排)
坑 1:Supabase 免費 tier 7 天 pause
最大的雷。Supabase 為了控制免費 tier 成本,專案連續 7 天沒查詢就會被 pause。pause 後使用者首次造訪會延遲 2-3 秒喚醒。
對 ClinCalc / ExClinCalc 沒上線給真實使用者前 ── 我自己一個禮拜不開系統很正常。導致面試前打開系統,被 pause、demo 卡住。
對策:GitHub Actions 每天 02:00 UTC ping 一次 Supabase health endpoint:
# .github/workflows/keepalive.yml
name: Supabase Keepalive
on:
schedule:
- cron: '0 2 * * *'
jobs:
ping:
runs-on: ubuntu-latest
steps:
- name: Ping Supabase
run: |
curl -X GET "${{ secrets.SUPABASE_URL }}/rest/v1/" \
-H "apikey: ${{ secrets.SUPABASE_ANON_KEY }}" \
-H "Authorization: Bearer ${{ secrets.SUPABASE_ANON_KEY }}"
從此沒再被 pause。
坑 2:CF Workers 不能直接連 PostgreSQL
Workers V8 isolate 早期不支援原生 TCP socket。直接 pg.connect() 不行。
對策:透過 Supabase 的 PostgREST HTTP API。多一層 HTTP 開銷,但 Workers 不用 manage TCP connection pool。Hyperdrive 現在能解但配置麻煩,對我規模不必要。
坑 3:Worker CPU 限制 10ms
免費 tier 每個請求 CPU 時間 10ms 上限。一般 API 沒事,但重度運算(PBKDF2 310,000 iterations、JSON.parse 大型 payload)會撞牆。
對策:
- 重度加密放使用者裝置(Kaizei 的 PBKDF2 在桌面 Electron 端跑)
- 大型 JSON 用 Streams API 邊讀邊處理
- 必要時升級到 paid Workers(每月 $5,CPU 上限 30s)
坑 4:Cloudflare KV 寫入有 strong consistency 延遲
KV 的 write 是 eventually consistent ── 寫入後可能要 60 秒才在所有邊緣節點看到。
對我影響不大(rate limit 容忍延遲),但**「寫入後馬上要讀到」的場景不能用 KV**。要用 D1(SQL)或 Durable Objects。
部署流程(10 分鐘上線)
如果你也想複製這個方案,從零部署一個 Astro 網站到 Cloudflare Pages:
# 1. 開 repo + push 上 GitHub(公開 repo)
git init
git add .
git commit -m "initial commit"
gh repo create my-site --public --source=. --push
# 2. 上 Cloudflare Dashboard → Pages → Create Project
# - Connect to Git → 選你的 repo
# - Framework preset: 你用的 framework(Astro/Next/Vite)
# - Build command: 自動填好
# - Build output: dist 或 build
# - Environment variables: 加你的 secrets
# 3. Save and Deploy → 5 分鐘後拿到 URL
# - https://my-site-xxx.pages.dev
之後每次 git push 自動 deploy。
這個方案的天花板
「$0 / 月」不是無限可擴。明確說一下天花板:
天花板 1:流量
Cloudflare Workers 免費:100K req/day
→ ~ 3M req/month
→ 約撐到 ~ 100,000 月活躍使用者(看使用模式)
如果 ClinCalc 突然爆紅(新聞報導),可能需要升級到付費 Workers ($5/月,無限請求 + 30s CPU)。但這時候已經有「值得付費的問題」可以解了。
天花板 2:資料量
Supabase 免費:500MB DB
→ 數十萬筆一般 row 數據
→ 約撐到中型診所(500 病人 + 多年病歷)
到極限要付 $25/月升 Supabase Pro(8GB DB + 無 pause)。
天花板 3:寫入併發
Supabase 免費 tier 連線數有限(PgBouncer 約 30 個 transaction pool)。如果 100 個使用者同時寫入 ── 排隊。
對單一診所沒問題,多診所同時上線可能有狀況。
天花板 4:客服 / SLA
免費 tier 沒有 SLA、沒有客服回應承諾。Supabase 真的掛掉 ── 等他們修。
對醫療正式上線是不能接受的。面試 / demo 階段可以,產品化要重新評估。
什麼時候該升級
我的決策樹:
免費 tier 跑得順 → 繼續免費
↓
某項服務開始抖(pause / 慢 / throttle)→ 看看是哪一項
↓
只是 keepalive 沒做好 → 修 keepalive,繼續免費
↓
真的負載上來 → 升級那一項,繼續其他免費
通常順序:Supabase Pro ($25) → Workers Paid ($5) → CF Pages Pro
不要從第一天就開全部付費。量化你的真實負載 → 找瓶頸 → 針對性升級。
不適合這個方案的情況
公平講 ── 不是所有專案都該走「$0 / 月」路線:
- 企業客戶要 SLA → 直接付費 / 自架
- 資料量很大(GB 級)→ 免費 tier 不夠
- 法規要求資料留特定 region → CF 全球邊緣可能不合
- 需要 stateful 長連線(WebSocket 24/7)→ Workers 不適合
- 需要 long-running compute → Lambda / VM 比較合
對「個人作品 / 學生 demo / 小規模初創前期」── 我這個方案非常合適。
一個觀察
走過這個方案兩年下來,最大的觀察是:
「免費 tier」不是單純省錢,是「強迫設計者問正確的問題」。
我為了塞進 100K req/day 上限,學會了在 Worker 內做有效快取。 為了 500MB DB 上限,學會了 schema 設計時就思考 storage growth。 為了 10ms CPU 上限,學會了把重度運算丟到客戶端。
這些技能在我之後做更大規模專案時也用得到。免費 tier 不是退路、是訓練場。
延伸閱讀
- 為什麼選 Cloudflare Workers 不選 AWS Lambda
- ExClinCalc Case Study ── 看 Worker + Supabase + RLS 的實際組合
- Kaizei Case Study ── 看零知識架構在這個 stack 上跑得順