系統設計 · 軟體工程

大公司裡的軟體開發:
寫 Code 之前,你該先想清楚的事

從「為什麼要做」到 Design Review,設計系統時該問哪些問題、每個問題背後在防什麼風險,用一個真實的例子從頭講到尾。

目錄
  1. 一、設計系統之前
    1. 為什麼要實作這項功能
    2. 要如何實作
    3. 用戶量級與資料量體
    4. 系統有哪些限制
    5. 每位使用者的成本
    6. 人力與時間
    7. 既有系統相容
  2. 二、設計時
    1. 用經營者的角度做決策
    2. PoC 與 Prototype
  3. 三、Design Review 時
    1. Q1 問題、功能與規模
    2. Q2 技術方案比較
    3. Q3 任務分派與佇列
    4. Q4 Stateless 與狀態
    5. Q5 擴容
    6. Q6 快取
    7. Q7 資料庫設計
    8. Q8 資料同步與併發
    9. Q9 日誌與稽核
    10. Q10 監控指標
    11. Q11 認證與授權
    12. Q12 成本與容量
    13. Q13 故障轉移
    14. Q14 錯誤處理
    15. Q15 支援平台
    16. Q16 系統限制
    17. Q17 問題排查
    18. Q18 資料保存時效
  4. 寫在最後

剛進大公司的工程師常常有個疑問:「明明兩天就寫得完的功能,為什麼要先寫設計文件、開好幾次會?」

老實說,我以前也這樣覺得。直到踩過幾次雷:功能上線才發現用戶根本不用、雲端帳單比省下的錢還多、半夜被叫起來處理一個沒人看得懂的系統。那時我才慢慢理解,在大公司,寫 Code 通常是最簡單的部分。難的是在寫之前,先把「會出事的地方」想清楚。

這篇文章把我自己設計系統時會問的問題,整理成三個階段:

  1. 設計系統之前:先搞清楚到底要解決什麼問題
  2. 設計時:用經營者的角度做決策
  3. Design Review 時:常被問的問題,以及它們背後想抓的風險

每個問題我都會講「為什麼要問」。了解問題背後要解決什麼,才能針對回答,不然就只是在背 checklist。

貫穿全文的例子

為了不要太抽象,我用同一個例子從頭講到尾:

公司有 1,000 位客服人員,每通電話結束後,要花 3 分鐘在 CRM 手打通話紀錄。老闆希望做一個「通話錄音自動摘要」功能:電話一掛掉,系統就自動把錄音轉成文字、產生摘要、填回 CRM。


PART 1一、設計系統之前

了解在開始設計前,需要考慮哪些問題。

1. 為什麼要實作這項功能?

這題最容易被跳過,但也最重要。工程師很容易一聽到需求就開始想架構:「要用哪個模型?要不要上 Kafka?」但如果連誰要用、解決什麼問題都不清楚,很可能會做出一個技術很漂亮、卻沒人想用的東西。

我會把它拆成三個小問題:

這個功能的用戶是誰?

「客服」只是第一層答案,再往下挖會發現其實有三種人:

三種人要的東西不一樣,權限也不一樣(客服不該看到別人的通話),這些都會直接影響後面的設計。

解決用戶什麼問題?

表面上是「省打字時間」,但實際算一下:每小時接 5 通、每通省 3 分鐘,等於每小時省 15 分鐘,一天就是 2 小時。1,000 位客服加起來,每天省下 2,000 小時的人力。

這個數字很重要,它決定了公司願意為這個功能花多少錢,後面算成本時會一直用到。

用戶以前是怎麼做的?

這題最常被忽略,卻最常救命。以前客服是在 CRM 的備註欄手打紀錄,主管要查客訴就去抽聽錄音。

這告訴我們一件事:摘要最後一定要回到 CRM。如果做成一個獨立網站,客服就得在兩個系統之間複製貼上,等於只是把「打字」換成「複製貼上」,用不到一個月就沒人用了。

背後要解決的問題

避免做出「技術上成功、商業上失敗」的功能。用戶的舊習慣,就是新系統的限制條件。

2. 要如何實作這項功能?

功能核心在哪?Endpoint / Cloud / Local Server

同一個功能,核心放在不同地方,結果差非常多:

核心位置以通話摘要為例好處代價
Endpoint(客服電腦)每台電腦自己跑語音辨識模型錄音不用上傳,隱私最好公司電腦沒有 GPU,跑不動;1,000 台電腦的模型更新是場惡夢
Cloud錄音上傳到雲端處理開發最快,要擴容就加機器錄音含個資,資安或法遵可能不准資料出公司
Local Server(公司機房)在機房架 GPU 伺服器資料不出公司要自己採購、維運硬體,擴容得等採購流程

客服錄音裡常常有客人念出身分證字號、信用卡號,所以這題通常不是工程師自己能決定的,要先問資安和法務。記得是先問,不要做完才問。

介面是什麼?Desktop App / Mobile App / Web

客服整天開著 CRM 網頁,直覺上做成 CRM 裡的 Web 外掛就好。

但這要看錄音從哪裡來。如果公司的電話系統(PBX)本來就會錄音,後端直接去拿檔案,前端只要做 Web 外掛顯示摘要。可是如果電話系統沒有錄音功能,得從客服電腦上擷取軟體電話(softphone)的聲音,瀏覽器就做不到了,只能做 Desktop App。而 Desktop App 代表要處理安裝、自動更新,還有公司電腦的權限管控。

一個看起來很小的需求細節,就決定了整個前端要怎麼做。

主要的技術框架是什麼?

語音辨識和 LLM 的生態系幾乎都在 Python,所以處理音訊的 worker 用 Python 很合理;負責大量併發請求的 API 服務,用 Go 可能更省資源。如果前端是 CRM 外掛,就得遵守那個 CRM 平台規定的開發框架,這部分沒得選。

背後要解決的問題

核心放哪、介面是什麼,決定了資料怎麼流、合不合規、維運成本多高,這些都是之後很難改的決定。

3. 用戶量級有多大?使用頻率?資料量體?

一定要有數字。「很多人用」不是規模,「1,000 人、每人每小時 5 次、每次 10MB」才是。

用我們的例子實際算一次:

假設
  • 使用者:1,000 位客服,只在上班時間(8 小時)使用
  • 頻率:每人每小時約 5 通電話
  • 檔案:10 分鐘的錄音,約 10MB
≈ 1.4 次平均每秒請求
(每小時 1,000 × 5 = 5,000 次)
≈ 110 Mbps上傳頻寬
(1.4 × 10MB ≈ 14 MB/s)
400 GB每天資料量
(5,000 × 8 小時 × 10MB)
8.8 TB每月資料量
(以 22 個工作天計)

有趣的地方來了:每秒 1.4 個請求,小到一台機器就扛得住;但每個月 8.8TB 的錄音,一年就超過 100TB。

這個系統的挑戰根本不在 QPS,而是頻寬、儲存成本和處理時間。沒算數字之前,很容易把力氣花在錯的地方,例如花兩週去調 API 效能。

「只在上班時間用」也是很重要的資訊:

背後要解決的問題

規模決定架構。1,000 人和 100 萬人的系統是完全不同的設計,沒有數字的討論都是空談。

4. 系統有哪些限制?

每種技術都有先天的瓶頸,最好在設計前就知道,而不是上線後才撞牆。

資料庫的 CAP 定理

分散式系統裡,一致性(Consistency)、可用性(Availability)、分區容錯(Partition tolerance)三者只能取其二。不過實務上網路一定會斷,分區一定會發生,所以真正的選擇其實是:網路出問題的時候,你要「資料一定正確」,還是「服務一定能回應」?

訊息大小與逾時限制

在我們的例子裡這點特別關鍵,因為每個錄音檔都有 10MB:

元件常見限制對 10MB 錄音的影響
AWS API Gateway(REST)Payload 上限 10MB,整合逾時預設 29 秒檔案大小剛好卡在邊緣;轉錄一通 10 分鐘錄音一定超過 29 秒
AWS Lambda(同步呼叫)Request / Response payload 上限 6MB直接塞不進去
Kafka單筆訊息預設上限約 1MB塞不進去
DynamoDB單筆 item 上限 400KB一份長一點的逐字稿就可能超過

知道這些限制之後,設計方向自然就出來了:

背後要解決的問題

避免設計到一半,甚至上線後,才發現某個元件根本扛不住,整個架構要打掉重來。

5. 每位使用者的成本是多少?

市場售價是多少?我們的目標是多少?就算是內部工具也要算,因為老闆一定會拿它跟「直接買現成的 SaaS」比。

假設(以下數字都是舉例)
  • 市面上類似的通話摘要服務,每位使用者每月約 30 美元
  • 我們每通電話的語音辨識加 LLM 摘要,成本約 0.02 美元
  • 每位客服每月約 880 通電話(5 通 × 8 小時 × 22 天)
運算成本:880 × 0.02 = 17.6 美元/人/月
儲存成本:每人每月新增 8.8GB,第一個月很少,但不刪的話會一直累積
每位使用者每月成本 ≈ 18 美元起跳,而且逐月上升

跟 30 美元比,看起來還有空間。但加上維運人力、機器閒置、儲存逐月累積之後,很可能就跟直接買差不多了。這時候設計方向就會跟著改變:

如果是要賣給外部客戶的產品,SaaS 常見的毛利目標在 70%~80%,換算下來,每位使用者的服務成本大約要壓在售價的兩到三成以內,才養得起團隊。

背後要解決的問題

功能做得出來,不等於應該做。成本決定這個功能能不能活下去,也會反過來決定架構:要不要自架、要不要快取、資料留多久。

6. 要達到正式上線的品質,需要投入多少人力與時間?

Demo 做出來,大概只完成了一半。

正式上線還需要監控告警、權限控管、資安審查、壓力測試、錯誤處理、on-call 手冊、文件……這些常常佔掉另一半甚至更多的時間,卻最常被忘記算進時程裡。

估時程時,我會把工作分成兩類:

有明顯 Gap、需要自己 build 的

例如客服電話裡常常國台語、中英文夾雜,現成的語音辨識準確率可能不夠。這種「目前沒有現成方案」的工作是研究型的,可能兩週就搞定,也可能三個月還在調。

這一塊一定要獨立拉出來估,並且講清楚它的不確定性,不要跟一般開發工作混在一起算。

有折衷方案可以暫時填補,但之後要改的

折衷沒有問題,但一定要寫進文件、開好 ticket、約好什麼時候還。沒被記錄下來的「暫時」,最後都會變成「永久」。

背後要解決的問題

讓主管對時程有合理的預期,也讓大家清楚知道有哪些已知的技術債。

7. 有哪些既有系統需要相容?

大公司不是一張白紙,你設計的東西要放進一個可能已經運作十幾年的環境裡。公司偏好的語言、系統、軟體、合作廠商,都是設計的前提。

公司偏好的程式語言

如果公司的人都是 Python / Golang 專家,就算你覺得 Elixir 超適合寫這個功能,也要三思。原因很現實:

選大家熟悉的語言,出問題時很快就有人能 review、能幫忙。

公司既有的平台與資料格式

例如公司的數據平台用 Starburst,偏好 Iceberg 格式。那通話摘要的歷史資料就應該落地成 Iceberg table,數據團隊馬上就能拿去分析,不用另外寫一套 ETL 轉換。

其他常見的相容性問題

背後要解決的問題

降低維運和溝通成本。系統不是寫完就結束,而是要有人長期照顧,要選公司「養得起」的技術。


PART 2二、設計時

用經營者的角度做決策

設計系統時,我覺得最重要的心態轉換是:想像這個功能是你自己開的公司,每個月的雲端帳單會寄到你家,半夜出事會打你的手機。

用這個角度看,你自然會在意下面這幾件事。

1. 可擴充性(Scalability):量變大時,加機器就好嗎?

公司明年併購了另一個客服中心,客服從 1,000 人變成 3,000 人。好的設計是「worker 從 5 台加到 15 台」就結束;不好的設計是「資料庫扛不住,要停機兩天做資料遷移」。

2. 可延展性(Extensibility):加新功能時,要重寫嗎?

可擴充性是「量」的問題,可延展性是「功能」的問題。上線三個月後,主管一定會說:「既然都有逐字稿了,可以順便做情緒分析嗎?可以自動判斷客訴類別嗎?」

如果轉錄完成時會發出一個「逐字稿已產生」的事件,新功能只要訂閱這個事件就能加上去。如果轉錄、摘要、寫回 CRM 全部寫死在同一個函式裡,每加一個功能都要動到核心流程,改一次就可能壞一次。

3. 費用可接受

前面算過的每位使用者成本,設計時要一直拿出來檢查。每加一個元件(快取、Queue、read replica)都要問自己:它帶來的好處,值得它的價錢嗎?

4. 維護難度可接受

自己架一套 Kafka + Kubernetes + Cassandra 聽起來很厲害,但如果團隊只有三個人,光是升級版本、處理節點掛掉,就會把整個團隊的時間吃光。

很多時候,用雲端的 managed service 多花一點錢,換團隊晚上能好好睡覺,是非常划算的交易。

5. 讓 Review 的人有選擇

這點很多人會忽略:至少設計兩個方案,並比較優缺點。

為什麼?如果你只給一個方案,reviewer 只能回答「好」或「不好」,而且他心裡一定會想:「你是不是沒想過別的做法?」接下來整場會議就會變成每個人各自提自己腦中的方案,討論完全發散。

如果你攤開兩個方案,討論就會聚焦在「我們要哪一種取捨」:

方案 A:雲端 Managed 服務方案 B:公司機房自架模型
上線時間約 2 個月約 5 個月(含 GPU 採購)
每月成本隨用量線性成長前期硬體投入高,量大時比較便宜
個資合規需要資安審查錄音能不能上雲資料不出公司
維運負擔低高,需要有人顧 GPU 和模型
擴容彈性高,隨時可以加低,要等採購
台語辨識受限於廠商支援程度可以自己 fine-tune

最後再加上「我推薦哪個方案,為什麼」。被淘汰的方案也值得留一行說明原因,半年後有人問「當初怎麼沒選 B?」,文件就是答案。

(接下來 Design Review 的例子,都假設我們推薦方案 A:資安審查通過錄音可以上雲,先用雲端服務快速上線。)

PoC 是驗證路走得通,不是做一套系統

這是非常常見的坑。

PoC(Proof of Concept)要回答的是一個很具體的問題:「這條路走得通嗎?」例如:

拿 50 通真實的客服錄音(包含台語、背景噪音、客人很生氣在大吼),跑語音辨識加摘要,看準確率能不能到 85%。

這個 PoC 不需要登入、不需要資料庫、不需要漂亮的 UI,一個 script 加一份結果報告就夠了,一到兩週內應該要有結論。做完之後 code 整包丟掉也完全沒關係。

常見的失敗劇本是這樣的:PoC 做著做著加了 UI、加了資料庫,拿去 Demo 給老闆看,老闆說:「這不是做好了嗎?下個月上線吧!」然後一個沒有權限控管、沒有監控、沒有錯誤處理的東西,就這樣上了 production。

Prototype 則是在設計決定之後,照著選定的架構做出來,給一小群真實用戶試用的版本。它要驗證的是流程與體驗:客服真的會看摘要嗎?摘要放在 CRM 哪個位置最順手?

順序是:

PoC 驗證可行性 設計與 Review Prototype 驗證體驗 正式開發
背後要解決的問題

用最少的成本排除最大的不確定性,同時避免「半成品意外上線」。


PART 3三、Design Review 時

Design Review 不是來刁難你的,是一群踩過雷的人在幫你找系統的風險。

而且目標不是零風險。零風險的系統不存在,就算存在也貴到做不起。真正的目標是:把「不知道的風險」變成「知道、而且選擇承受的風險」,並講清楚代價是什麼。

例如:

下面是 Design Review 常被問到的問題。每一題我都附上「它背後想抓什麼風險」,準備時先想清楚這個,回答起來會有方向很多。

Q1系統要解決什麼問題?提供哪些功能?預期的規模有多大?

背後想抓的大家講的是不是同一件事。

這題通常第一個被問。如果一兩句話講不清楚,後面的討論都會失焦。好的回答要有用戶、有價值、有數字:

「讓 1,000 位客服在每通電話結束後 1 分鐘內拿到摘要,省下每通 3 分鐘的手打時間。尖峰每小時約 5,000 通,每月約 8.8TB 錄音。」

另外建議明確寫出這一版不做什麼(Non-goals),例如「不做即時字幕、不做情緒分析」。不寫的話,會議開到一半一定有人說:「那順便做 XX 應該不難吧?」

Q2有哪些可選擇的技術方案?各自的優缺點是什麼?

背後想抓的你是真的比較過,還是先有答案才去找理由。

這就是前面「至少兩個方案」的比較表。Reviewer 會特別注意比較是不是公平:如果推薦方案的優點寫滿滿、另一個方案只寫缺點,大家很快就看得出來那是稻草人。

誠實寫出推薦方案的缺點,反而更有說服力。

Q3任務如何分派?同步還是非同步?需要佇列嗎?佇列長度與逾時怎麼管理?

背後想抓的尖峰時系統會不會崩、使用者要等多久、任務會不會掉或重複執行。

轉錄一通 10 分鐘的錄音可能要 30~60 秒,前面提過 API Gateway 預設 29 秒就逾時,所以同步處理行不通。流程會變成:

客服掛電話 錄音上傳 S3 任務進入 Queue Worker 轉錄、摘要 寫回 CRM 通知客服畫面更新

用了 Queue 之後,接著一定會被追問:

Q4核心工作負載是 Stateless 還是 Stateful?使用者狀態怎麼記錄、保留與還原?需要 Session Sticky 嗎?

背後想抓的機器能不能隨便加、隨便砍?機器掛了,使用者會不會掉資料?

Stateless 代表任何一台機器都能處理任何一個請求,機器掛了換一台就好,要擴容就加機器。Stateful 代表有些資料只存在某台機器的記憶體裡,那台一掛,資料就跟著不見。

舉例:如果 worker 把「這通錄音處理到第幾段」記在記憶體裡,autoscaling 一縮容把機器砍掉,這通就得從頭來。正確做法是把進度寫進資料庫或 S3,讓 worker 本身不留任何狀態。

比較麻煩的是通知客服「摘要好了」這件事。如果用 WebSocket 推播,連線本身就綁在某台機器上,天生就是 stateful 的。常見做法有兩種:

至於還原:客服斷線重連時,前端用 call_id 去資料庫查最新狀態,不依賴「剛才那條連線記得什麼」。

Q5隨著使用者與資料成長,系統要如何擴容?Stateless 橫向擴展,還是 Sharding?哪些指標會觸發擴容?

背後想抓的成長的時候是「加機器」就好,還是得「重新設計」?

成長有兩種,要分開看。

使用者變多(請求變多):Stateless 橫向擴展

客服從 1,000 人變成 3,000 人,只要 API 和 worker 都是 stateless,加機器就解決了。

資料變多(單表變大):Partition、冷熱分離、Sharding

一年後資料庫裡有上千萬筆通話紀錄,主管查「過去一年所有客訴」越來越慢。這時候加 API 機器沒有用,瓶頸在資料庫。可以依序考慮:

  1. 依月份做 partition,查詢只掃需要的月份
  2. 超過一年的冷資料搬到 Iceberg,用 Starburst 查(剛好是公司既有的平台)
  3. 真的扛不住寫入量,才考慮 sharding

Sharding 最關鍵的是 shard key 怎麼選。例如用「日期」當 shard key,今天的資料全部落在同一個 shard,那個 shard 永遠最熱,其他 shard 閒著沒事,等於沒切。改用「客服中心 ID」或「客服 ID」會平均很多。Shard key 選錯之後幾乎沒辦法改,所以 reviewer 通常會問得很細。

觸發擴容的指標

很多人直覺用 CPU,但在我們的例子裡這是錯的。Worker 大部分時間都在等外部語音辨識 API 回應(I/O bound),CPU 可能只有 20%,Queue 裡卻已經積了 2,000 筆。用 CPU 當觸發條件的話,永遠不會擴容。

比較好的指標是:

Q6系統需要快取嗎?TTL 設多久?如何避免資料不一致?

背後想抓的快取是「用一致性換速度」,你知道自己換掉了什麼嗎?

先講一件事:不是每個系統都需要快取。1,000 人的內部系統,資料庫可能完全扛得住。多一層快取,就多一個資料不一致的來源。先量測,確定有需要再加。

如果真的需要,要依資料性質決定:

後者的做法是寫入時主動清掉快取(更新資料庫後刪掉對應的 cache key),TTL 只當作最後一道保險。

另外還有一個常見的坑:快取雪崩。如果大量 key 在同一時間寫入、TTL 又都一樣(例如早上 9 點批次載入、TTL 都是 1 小時),10 點整所有快取同時失效,流量全部打到資料庫。解法是在 TTL 上加一點隨機值(jitter),例如 55~65 分鐘,讓過期時間錯開。

Q7資料庫怎麼設計?CAP 如何取捨?讀寫分離、Sharding、備份與還原、Multi-AZ、I/O 容量?

背後想抓的資料庫是系統裡最難事後修改的部分,一開始沒想好,之後的代價最高。

CAP 取捨

同一個系統裡,不同的資料可以有不同的選擇。「一通電話只能有一份正式摘要」這種對應關係必須強一致;統計報表則可以接受最終一致。

讀寫分離

主管跑大報表很吃資源,丟到 read replica 去跑,才不會拖慢客服的寫入。但要注意 replica 會有延遲(replication lag):客服剛存完摘要,畫面馬上去 replica 讀,會發現「咦,怎麼沒存到?」所以讀自己剛寫入的資料要走 primary。

備份與還原

「有備份」不等於「能還原」。Reviewer 很可能會問:你實際還原過嗎?還原 2TB 要幾個小時?這段時間系統怎麼辦?

沒演練過的備份,通常到出事時才會發現少備了某張表,或是還原要 12 小時。

Multi-AZ

一個機房(Availability Zone)斷電或斷網時,資料庫能不能自動切到另一個機房?代價是成本大約翻倍,所以要評估「停機一小時」的損失有沒有比這筆錢高。

I/O 容量

雲端硬碟有 IOPS 上限(例如 AWS gp3 的基準是 3,000 IOPS)。常見的狀況是:半夜的批次報表把 IOPS 吃滿,線上寫入跟著變慢,看起來像資料庫當掉了,但 CPU 其實很閒。沒在看 I/O 指標的話,會查很久。

Q8資料同步怎麼設計?如何控制多人同時存取資料?

背後想抓的兩個人同時改同一筆資料時,會不會有人的修改默默消失?

情境

客服正在修改某通電話的摘要,同一時間主管在同一筆紀錄上加註記。主管先存,客服後存,主管的註記就被蓋掉了,而且沒有任何人發現。這叫 Lost Update。

常見解法:

跨系統的資料同步又是另一個問題:摘要要寫回 CRM,但如果 CRM 的 API 剛好掛了呢?

Q9日誌怎麼收集?可以分析哪些錯誤?能查詢系統異常事件嗎?使用者操作有保留稽核日誌嗎?

背後想抓的出事的時候,你查得出來發生了什麼事嗎?

情境:客服反映「我昨天下午那通電話沒有摘要」。如果 log 只是一行一行的文字,沒有任何 ID 串起來,你就只能在幾百萬行 log 裡大海撈針。

幾個基本原則:

稽核日誌(Audit Log)則是另一回事。通話錄音含有客戶個資,資安稽核或發生外洩事件時,一定會被問:「誰、在什麼時間、聽了哪一通錄音、下載了哪份摘要?」這類日誌要跟一般 log 分開存、不能被竄改,保存期限依公司政策或法規決定。

Q10系統要監控哪些指標?CPU、記憶體、磁碟、網路、請求量、快取命中率、連線池大小與延遲?

背後想抓的你能不能比使用者更早知道系統出事了?

我會把指標分成兩層:

幾個真實會發生的例子,說明為什麼這些指標很重要:

Q11認證與授權怎麼運作?如何避免使用者存取他人的資料?支援哪些登入方式?帳號怎麼註冊?

背後想抓的資安漏洞,而且是最常見、最嚴重的那一種。

先分清楚:認證(Authentication)是「你是誰」,授權(Authorization)是「你可以做什麼」。

最常見的漏洞叫 IDOR:客服打開 /calls/12345/summary 看自己的通話,好奇把網址改成 12346,結果就看到別人的通話了。

只在前端把按鈕藏起來是沒用的,每一支 API 都要在後端檢查這個人有沒有權限看這筆資料。例如:是自己的通話,或者身分是主管、且這通是自己組員的通話。

登入方式:企業內部系統請直接接公司的 SSO(用 SAML / OIDC 接 Azure AD、Okta)。自己做帳號密碼最大的問題是:員工離職後 AD 帳號停用了,但你系統裡的帳號還在,他照樣能登入。

帳號註冊:內部系統通常不開放自行註冊,而是從 AD 群組同步(例如透過 SCIM),人事異動時權限會自動跟著變。

Q12系統成本是多少?可承受多少流量?每個服務單元可支援多少用量?

背後想抓的你對系統容量有「實測過的數字」,還是只是用猜的?

「服務單元」指的是一台 worker、一個 pod 能處理多少量。這個數字要用壓測量出來,有了它,擴容和成本才算得出來:

壓測結果:一台 worker 每分鐘可以完成 12 通 10 分鐘的錄音
平常尖峰:5,000 通/小時 ≈ 83 通/分鐘 → 需要 7 台
預留容錯(掛 2 台還撐得住)→ 9 台
月初 3 倍流量:約 250 通/分鐘 → 需要 21 台以上

有了台數,乘上單價就是每月成本,再除以使用者人數,就回到前面「每位使用者成本是多少」的問題。

也要講清楚超過可承受流量時會怎樣:排隊變慢?限流(rate limit)直接拒絕?還是降級成只做轉錄?

Q13各系統元件的故障轉移機制是什麼?恢復需要多久?

背後想抓的每個元件都會壞,壞掉的時候使用者會看到什麼?

有兩個常用的指標:

建議把每個元件列出來,一個一個回答:

元件故障情境故障轉移方式恢復時間
API Server其中一台掛掉多台放在 Load Balancer 後面,自動剔除幾乎無感
Worker處理到一半掛掉任務逾時後回到 Queue,由其他 worker 接手該通延遲幾分鐘
資料庫Primary 掛掉Multi-AZ 自動切換約 1~2 分鐘,期間寫入要能重試
錄音檔(S3)單一機房故障S3 本身跨 AZ 儲存,耐久性極高RPO 必須是 0,錄音絕對不能丟
外部語音辨識 / LLM API廠商服務中斷任務留在 Queue 等恢復,或切換到備援廠商看廠商;期間客服先手打

最後一列是最常被忘記的。外部依賴壞掉的時候,你完全修不了,只能事先想好備案。另外,摘要壞了可以重新產生,錄音不見了就沒了,所以兩者的 RPO 要求完全不同。

Q14錯誤處理策略是什麼?輸入要驗證或限制嗎?輸出要分頁嗎?失敗要重試嗎?重試幾次、間隔多久?

背後想抓的永遠不要相信輸入,永遠假設呼叫會失敗。

輸入驗證

情境

客服忘記掛電話,錄了一整晚,產生一個 3GB 的錄音檔。Worker 載入時記憶體不足(OOM)當掉,任務回到 Queue,被另一台 worker 拿到又當掉……一台接一台掛,整個 Queue 卡死。這種會一直讓處理者當掉的訊息,叫做 Poison Message。

所以輸入一定要設限制:

輸出分頁

主管查「本月所有通話」,API 一次回傳 10 萬筆,結果 API 逾時、瀏覽器卡死。清單類的 API 一定要分頁;資料量大時,建議用 cursor-based pagination,而不是 OFFSET(越往後翻越慢)。

重試策略

Q15支援哪些平台?需要響應式設計(Responsive Design)嗎?

背後想抓的每多支援一個平台,就多一份開發、測試和維護的成本,你確定真的需要嗎?

明確寫出「不支援」的平台也很重要,例如「不支援手機上傳錄音」,免得上線後被當成 bug 回報。

Q16系統有哪些限制?在什麼情況下會觸發?

背後想抓的你知道自己系統的極限在哪嗎?撞到的時候會發生什麼事?

設計前問的「限制」,是外部技術的限制;這裡問的是你自己系統的限制。每一條都要寫清楚「什麼情況會觸發」,以及「觸發時系統會怎麼反應」:

限制什麼時候會觸發觸發時的行為
單檔上限 50MB(約 50 分鐘)技術支援電話常常超過 1 小時拒絕處理,提示「請手動紀錄」
處理量上限每分鐘約 250 通月初帳單寄出後排隊,摘要延遲產生
LLM API 每分鐘 token 上限尖峰時段收到 429 後退避重試
只支援國語與英語台語通話標記「辨識信心低,請人工確認」

把這些寫下來,半夜的 incident 就會變成「文件裡寫好的已知行為」,客服主管也能事先知道要怎麼應對。

Q17要如何排查系統中的問題?系統記錄了哪些關於使用者和系統狀態的資訊?

背後想抓的系統的「可除錯性」有沒有在設計時就考慮進去,還是出事了才來補 log。

用一個真實的排查過程,來看看需要哪些資訊。

客服小美回報:「我 10:32 那通電話的摘要是空的。」
  1. 用小美的使用者 ID 加上時間,找到那通電話的 call_id
  2. 用 call_id 找到 trace:上傳成功、Queue 有收到、轉錄也完成了,但逐字稿長度是 0
  3. 看錄音檔資訊:檔案大小正常,但取樣率是 8kHz,前一天之前都是 16kHz
  4. 看當時的系統狀態:電話系統前一晚升級,預設錄音格式被改掉,語音辨識吃到不支援的格式,回傳空結果卻沒有報錯
  5. 結論:不是模型壞了,是上游格式變了。而且我們的系統「安靜地失敗」,這本身也是要修的問題:逐字稿為空應該視為錯誤,並觸發告警

要能順利走完這條路,事先就要記錄:

特別是版本資訊。「只有 2.3.1 版的客戶端會出問題」、「電話系統升級後才開始壞」這種結論,沒記版本的話永遠查不出來。

Q18資料保存時效是多久?系統可以接受嗎?

背後想抓的資料不刪,成本會無限成長;資料留太久,法規和外洩的風險也跟著變大。

回頭看前面算的數字:每月 8.8TB 錄音,如果永久保存,一年後超過 100TB,三年後超過 300TB。以 S3 Standard 大約每 GB 每月 0.023 美元粗估(實際價格依區域而定),一年後光是錄音儲存,每個月就要兩千多美元,而且還在持續增加。

常見做法是依照資料的使用頻率分層:

時間儲存方式用途
30 天內一般儲存(S3 Standard)客服、主管常常需要回聽
30 天~1 年低頻或封存儲存客訴爭議時調閱,單價便宜很多
超過保存期限自動刪除(Lifecycle Policy)降低成本與個資風險

保存期限不是工程師自己定的,要找法務和資安一起決定:

最後一個常被忽略的細節:刪除要刪乾淨。錄音刪了,但備份、log、衍生出來的逐字稿、摘要、搜尋索引都還在,其實就等於沒刪。


WRAP-UP寫在最後

這些問題看起來很多,但不需要每一題都拿滿分。它們的目的不是讓設計文件變厚,而是幫你做到三件事:

先搞懂問題

誰用、解決什麼、以前怎麼做、規模多大、成本多少。

給出選擇

至少兩個方案,誠實比較取捨,寫下推薦的理由。

把風險攤開

哪些風險可以承受、代價是什麼,哪些絕對不能妥協。

在大公司,一個設計決定會影響好幾個團隊、好幾年的維運。花一兩週把這些問題想清楚,換來的是上線後少踩好幾個月的雷。

下次寫設計文件卡住的時候,不妨先把自己當成 reviewer,把這些問題問自己一輪。答得出來的,寫進文件;答不出來的,那就是你還沒想清楚的地方。

← 回到部落格 看看 Arlo AI 的開源專案