工程師創業初期遇困,改用這套 API 設計模式逆轉產品困境

Published on: | Last updated:

47 個 REST endpoint。主畫面一次要打 8 到 15 次 API call。每個 call 200–400ms。慢網路直接拖到 5–6 秒。GraphQL + Apollo Client 把它壓到 0.8 秒,Series A 才沒翻車。

  • 8 個 endpoint 疊一起,體感像在等電梯卡樓層
  • Over-fetching 一路燒 AWS bandwidth,手機電量也被你吸乾
  • GraphQL resolver 先包在現有 REST 上面,不用全砍重練
  • 先遷移 dashboard 這種「最常被看」的頁面,立刻回血

那個 23 秒的凍結真的會要命

投資人 demo 當場卡住 23 秒,常見原因不是「網路問題」,而是 REST 的多次往返、N+1 請求、過量 payload 讓主畫面渲染被勒死。

你知道最尷尬的是什麼嗎。

不是慢。

是你明明看著 log 跟 waterfall,心裡也知道哪裡在噴火,嘴巴還得講「應該是網路」。那個「應該」兩個字,會讓人想把筆電闔起來。

講到 waterfall,我突然想到一堆團隊只看 TTFB 不看「call 數量」,結果把 CDN 調到飛起來,手機端還是慢。因為你在等第 8 個 request 回來。第 8 個。很荒謬。

Type 1 Flowchart:主畫面變慢的判斷路徑
Type 1 Flowchart:主畫面變慢的判斷路徑

REST 不是罪犯 亂長才是

REST 在 MVP 階段常常跑得動,但 endpoint 數量失控時,會出現 chatty API(頻繁小請求)與 over-fetching(拿太多用不到欄位)兩個硬傷。

原文那個例子超典型。

主畫面要顯示「使用者概覽 + 公司資訊 + 交易 + 餘額 + 未付發票 + 分析 + 通知數 + feature flag」。你用 REST 切得很乾淨,工程師看了覺得舒服。

手機端會哭。

因為它要打:

  • /api/users/profile
  • /api/business/details
  • /api/transactions/recent
  • /api/accounts/balances
  • /api/invoices/pending
  • /api/analytics/monthly
  • /api/notifications/count
  • /api/features/flags

八次往返。

每次 200–400ms。你就算每個都「不算太慢」,加起來就是慢。還有 TLS handshake、行動網路抖動、Radio tail time 那些鬼東西,手機端你真的別跟它硬碰硬。

欸對了,原文還提到交易資料一次回 47 個欄位,手機只顯示 6 個。這就是 over-fetching 的標準教材。

關鍵:你以為你在省開發時間,實際上你在買未來的痛。

Type 2 Infocard:REST 變慢的四種常見長相
Type 2 Infocard:REST 變慢的四種常見長相

GraphQL 這招狠在一次拿齊 還只拿要的

GraphQL 透過 schema(型別契約)與 query(查詢語句)讓 client 一次請求拿到所需欄位,避免多次 REST 往返與 over-fetching,常用搭配是 Apollo Client(快取與 optimistic updates)。

我知道你會想吐槽。

「GraphQL 不就又多一層嗎」

對。就是多一層。

但那層是你可以控制的層。你把「資料怎麼拼」的決策權從一堆 endpoint 拉回 schema 上。手機端要什麼欄位,自己講清楚。後端照契約給。

原文那個 query 我直接保留概念,因為它很乾淨:

query DashboardData {
  user {
    name
    email
    businessName
  }
  accounts {
    balance
    currency
  }
  transactions(limit: 10) {
    id
    amount
    description
    date
  }
  notifications {
    unreadCount
  }
}

一次 request。

一次 response。

欄位剛好。

你看了就知道為什麼他們從 5.2 秒掉到 0.8 秒。這不是玄學。這是網路 IO 變少,payload 變小,渲染 pipeline 不卡。

三週遷移不翻車的做法 其實很俗又很有效

GraphQL migration 最穩的路線是「保留既有 REST,新增 GraphQL BFF 層」,讓 resolver 去呼叫內部 REST 服務,前端用 feature-by-feature 漸進切換。

這段我超有感。對,就是這個感覺!

因為一堆人一聽到要換架構,就手癢想「重寫」。重寫很爽。也很容易死。

原文的做法其實就是 BFF(Backend for Frontend)那一套,只是用 GraphQL 當介面:

  • REST endpoint 先留著,能跑的先別動
  • GraphQL layer 疊上去,resolver 內部打既有服務
  • 先搬「dashboard」這種 ROI 最高的頁面
  • 用 Apollo Client 把 cache、optimistic update 這些麻煩事外包掉

我自己覺得最爽的點不是效能。

是團隊節奏。

原文說 developer velocity 變 2x。你想像一下,原本每加一個小卡片,就要開一支 endpoint、改文件、改權限、改序列化欄位、改手機端 aggregator。

現在變成「schema 加欄位,client query 拉欄位」。事情突然變短。短到你會懷疑人生。

Type 3 Multi-view Diagram:同一個 dashboard 的三種視角
Type 3 Multi-view Diagram:同一個 dashboard 的三種視角

進階指標別只看秒數 要看可維護性跟成本噴點

API 架構評估不只看 dashboard load time,還要看「每頁 API call 數」「payload 大小」「schema 變更摩擦」「AWS egress 成本」這類核心指標,因為它們會直接回到留存與開發速度。

秒數當然好懂。

投資人也愛聽。

但你我都知道,最可怕的是那種「每做一個功能就多兩個 endpoint」的增生速度。你會開始怕加需求。怕到最後 PM 也不敢問。

原文有一句我很想翻成工程師人話:technical debt 不是 code style 的潔癖,是你產品體驗跟錢在流血。

對了,fintech 類在台灣還會多一層壓力。

金流、個資、權限。

GraphQL 不會幫你解決授權,還可能讓你把「資料暴露面」做更大。你得把 authz(授權規則)塞進 resolver 或 field-level policy。這塊偷懶會出事。

提示:工具層可以用 Apollo Studio(GraphQL 的觀測與 schema 管理)或至少把 query complexity、rate limit 做起來,避免被一條肥 query 拉爆。

台灣通路內行人避雷指南 買服務買顧問都算

在台灣導入 GraphQL 或 API 重構,最常踩雷的是「只買到 code,買不到規範與治理」,採購前要盯 schema ownership、權限模型、observability 方案三件事。

你要我講通路。

好。

這邊不是買牙膏啦,但採購邏輯很像。

常見路線就三種:接案公司、系統整合商、雲端顧問/自由接案。你在台北、竹北、新竹科學園區周邊問一圈,報價會跳得像心電圖。

價格區間我不給你精準數字,因為每家差太多,還牽涉 scope、資安、SLA。

我給你避雷清單。比較實在。

  • 合約沒寫 schema 管理責任:誰 review breaking change,誰扛版本策略,沒寫就等著互丟鍋。
  • 只談 GraphQL server 不談觀測:沒有 tracing、沒有 query log,出事你只能靠祈禱。
  • 權限模型含糊:一句「我們會做 JWT」就想帶過,這種我會直接打叉。JWT 是身份驗證,不是授權。
  • 把 DataLoader 當魔法粉:N+1 問題能緩解,不代表你可以不設計資料聚合邏輯。
  • 交付物只有程式碼:沒有 schema 文檔、沒有範例 query、沒有 runbook,後面維運就是地獄。

通路細節也補一點在地的。

台灣很多團隊會在 PTT Soft_Job、Tech_Job 或 Dcard 工程師相關版問「要不要導 GraphQL」。討論很熱。意見也很兩極。

你不要看熱鬧。

你去看他們在吵什麼:權限、效能、團隊學習曲線。那才是會把專案拖死的東西。

Type 4 Comparison Chart:REST 續命 vs 疊 GraphQL BFF vs 全面重寫
Type 4 Comparison Chart:REST 續命 vs 疊 GraphQL BFF vs 全面重寫

FAQ 你一定會問的那幾句 我先擋一下

規則:這段每題先直答,後面才碎碎念。

GraphQL 真的比 REST 快嗎?

GraphQL 的加速來源是減少往返次數與避免 over-fetching,像主畫面從 8 次 API call 變 1 次時,端到端延遲常會明顯下降。

快不快還是要看 resolver 背後怎麼打資料源,亂打一樣慢。對。就這樣。

已經有一堆 REST endpoint 了 要怎麼導入?

既有 REST 保留,先加一個 GraphQL layer 當 BFF,resolver 內部呼叫原本服務,再挑一個高頻頁面做漸進遷移。

你不要一次搬全站。會爆。

Apollo Client 值得用嗎?

Apollo Client 在快取、狀態管理、optimistic updates 上能省掉大量前端工時,特別適合行動端與資料互動密的產品。

代價是你得接受它的心智模型,還有 cache 調教。有人愛有人恨。

GraphQL 有什麼坑最常踩?

GraphQL 最常見的坑是 N+1 查詢、權限控管做太鬆、query complexity 沒限制,導致單一查詢拖垮後端資源。

還有 schema 亂長。你以為你在自由,實際上你在放生。

那個 Series A 沒翻車的真正原因 是決策速度

把 REST 亂象收斂成 GraphQL schema,等於把「資料需求」變成可協作的契約,讓小團隊在 18 天倒數時仍能用 3 週做出可驗證的性能改善。

原文講得很戲劇化。

我反而覺得它很冷。

冷在你被逼到牆角時,還願意做「看起來很冒險」的決定。繼續補洞其實更冒險。你只是拖延而已。

講到這個詞「拖延」,我又想到很多產品把慢當成「使用者忍一下」,結果留存掉了才開始緊張。留存掉了還想用行銷補。補不回來的啦。

Type 5 Two-column Trend Compare:常見誤解 vs 新的理解
Type 5 Two-column Trend Compare:常見誤解 vs 新的理解

免責:這篇是工程決策經驗整理,不是投資建議,也不是資安或法遵的正式意見;涉及金流與個資時,請依公司法遵與主管機關要求設計與審查。

我那時候會做的第一個小動作很土。

打開手機的 network profiler。看「主畫面到底幾個 request」。把那個數字寫在白板上。不要討論。先寫。

Related to this topic:

Comments

撥打專線 LINE免費通話