Skip to content

Product Builder 面試日練 — 2026-10-31:Technical PM

2026年10月31日1 分鐘
TL;DR今天的骨架是兩層:先用「五條獨立線」把一句話的技術需求拆成五個不能互相替代的面向——存取權限、吞吐量上限、預算額度、輸出品質、可預期的失敗行為——避免把「加個警示」講成「做了硬性管控」;再用「原子預留 → 對帳釋放」處理併發請求搶同一筆資源時的競態:天真作法是兩個請求各自讀一次餘額、各自核准,結果超支;正確作法是用一次性的原子扣減擋下第二個請求,等第一個請求實際結算後再核銷差額、釋放剩餘額度。練習題是 PracHub 改編自 OpenAI「Product Manager, API Infrastructure」職缺描述的企業 API 預算控管案例:剩餘授信 $12,兩個請求各要保留 $8,天真系統會核准兩次變成授權 $16 比 $12 還多;拆解示範先把「警示」和「硬擋」定義成兩個不同產品、再用原子預留處理併發,最後用小範圍試跑+對帳準確率衡量成功。案例是 Stripe 2017 年公開的 idempotency key 機制:同一個 idempotency key 在 24 小時內重複送出,Stripe 回傳第一次請求的結果而不是再扣一次錢,這套「先鎖定、重試認得出來」的邏輯跟今天練習題要解決的競態問題是同一個底層原理,現行官方文件在 2026 年仍明文保留「併發執行時的衝突不儲存冪等結果」這條規則。

查詞與收藏

正在載入查詞工具…

🌏 English version

今日主題

星期六輪到 Technical PM。這類面試最常見的失分模式不是知識量不夠,是把好幾個不同的技術限制混成一句話講——「加個預算警示」聽起來像個完整答案,但警示系統和硬性擋下超支是兩個不同的產品,混著講會在面試官追問「那併發的兩個請求呢」的時候當場穿幫。今天先練怎麼把一個模糊的技術需求拆成互不替代的幾條線,再練一個併發系統設計裡幾乎必考的子問題:兩個同時發生的動作搶同一筆有限資源時,怎麼保證帳不會算錯。

核心框架速記

五條獨立線:存取、吞吐量、預算、品質、可靠度不能互相替代

拿到一個技術需求時,候選人最常犯的錯是把好幾個不同維度的限制都說成「限制」。OpenAI 官方的 API 生產指南把成本、延遲、品質三者放在一起討論,但刻意強調它們是互相牽動、而非互相替代的關係——同一套邏輯可以延伸成五條線:

維度問的是什麼常見混淆
Access(存取)這個身分允不允許用這個專案/模型/功能跟「有沒有額度」混為一談
Throughput(吞吐量)服務現在接不接得住這個流量跟「有沒有授權花這筆錢」混為一談
Budget(預算)這個週期還授不授權再花錢跟「品質夠不夠好」混為一談
Quality(品質)輸出有沒有達到這個應用的接受標準跟「HTTP 回了 200」混為一談
Reliability(可靠度)使用者能不能預期失敗、復原、服務行為跟「現在沒出錯」混為一談

這五條線的用處在於互相拆解:吞吐量上限提高,不代表預算授權增加;換一個更便宜的模型,不代表品質可以接受;一個成功的 HTTP 回應,不代表使用者真正拿到有用的結果。被問「這個系統要怎麼設計限制」時,先把這五條線分開回答,而不是籠統地說「要考慮效能和成本」,是技術 PM 面試裡最容易立刻拉開差距的地方。

原子預留 → 對帳釋放:兩個併發請求搶同一筆預算,誰先擋下第二個

這題是技術 PM 系統設計裡的經典子問題:有限資源被兩個同時發生的請求搶,先讀後寫的天真實作一定會超發。正確作法是把「檢查額度」和「鎖定額度」合併成一次不可分割的動作:

兩個併發請求搶同一筆預算的准入時序
兩個併發請求搶同一筆預算的准入時序兩個請求同時想保留同一筆 $12 預算,分類帳用一次性的原子扣減擋下第二個請求,等第一個請求實際結算後再核銷差額、釋放剩餘額度。 預留 $8 核准,剩 $4 預留 $8 拒絕,剩 $4 完成,花 $6 核銷,剩 $6 Request A 預算分類帳 Request B
  1. Request A 送出預留,鎖住 $8
  2. 分類帳核准,剩餘額度降到 $4
  3. Request B 送出同樣的預留請求
  4. 分類帳拒絕(可用額度不足),剩餘仍是 $4
  5. Request A 完成,實際只花了 $6
  6. 分類帳核銷差額,剩餘回升到 $6

簡化自 PracHub 改編 OpenAI API Infrastructure PM 職缺的企業預算控管練習題;真實系統還要處理逾時與未結算工作的對帳,正文另有說明。

這張圖的重點是:如果分類帳不是原子扣減,而是「先讀餘額、再各自核准」,兩個請求會各自看到 $12 可用,各核准 $8,變成授權 $16 比剩餘的 $12 還多。原子預留把「檢查」和「鎖定」黏成一步,才能保證第二個請求一定看到第一個已經鎖走的額度。而這個保留只是暫時估計值,等第一個請求真正結算(花了 $6,不是預估的 $8)之後,還要再核銷差額、把多保留的 $2 還回去——這一步常被候選人漏講,但正是「能不能真的叫做硬性控管」的關鍵。

今日練習題

題目

「一家企業內部的文件助理系統,有三種人要顧:財務想要每月花費可預期,應用負責人想讓正式環境的請求不要被擋下來,平台管理員想要開發環境和正式環境有不同的權限。用量紀錄會在工作已經開始執行之後才進帳,而且有些請求是同時發生的。你會怎麼設計一套預算控管功能?」

(來源:PracHub《OpenAI Product Manager Interview Preparation: Product Judgment and API Trade-Offs》,根據 OpenAI 官方「Product Manager, API Infrastructure」職缺描述改編的原創練習題,非官方回報的真實面試題;文中金額、客戶與門檻皆為示範用的虛構數字)

拆解思路

  1. 釐清問題:先問這題的「預算控管」指的是示警還是硬擋——「用量接近預算就提醒」和「可能超支就直接擋下新工作」是兩個不同的產品,混著講會在後面的追問中站不住腳。同時要問清楚三種既有允許額度(專案層、組織層)之間能不能互相挪用,這屬於產品規則,不是技術細節可以延後決定。
  2. 定義使用者與現有行為:分開訪談財務、應用負責人、平台管理員三種人——問他們現在事故發生時會先關掉什麼、共用的預算怎麼手動分配、一次誤判的拒絕會造成什麼傷害。財務可能偏好嚴格管控,應用負責人可能認為同一套嚴格管控在營運上很危險,這個拉力要在設計前講清楚,不能假設兩邊想要一樣的東西。
  3. 結構化分析:用「五條獨立線」把這題拆開——存取權限(開發環境和正式環境誰能用)、吞吐量(服務現在接不接得住)、預算(這個週期還能不能花)、品質(換便宜模型值不值得)、可靠度(使用者能不能預期拒絕之後會發生什麼)。這題的核心其實只落在預算和可靠度這兩條線,先講清楚範圍再往下走。
  4. 提出方案:用「原子預留 → 對帳釋放」處理併發請求搶同一筆預算的競態,而不是只畫一個即時更新的用量圖表——好看的圖表不能修補一個會重複核准的承諾。初版先開放小範圍、已經理解拒絕行為的正式環境管理員試跑,而不是一次全面上線。
  5. 定義成功:指標要包含政策理解度(使用者知不知道被拒絕時該做什麼)、對帳準確率(保留額度跟實際扣款的誤差)、false rejection rate(錯誤擋下本該放行的工作)、支援負擔,而且要按工作負載分開看——一個漂亮的整體平均數可能蓋住某一個關鍵應用被整組擋死的事實。

範例回答(面試時可以這樣講)

先把「示警」和「硬擋」當成兩個不同的產品來問,不要假設。 我會先問清楚這題要的是「用量接近預算就提醒」,還是「可能超支就直接擋下新工作」——這兩個答案會完全決定接下來的設計方向。我也會分開訪談財務、應用負責人、平台管理員,因為財務可能想要嚴格管控,但應用負責人很可能認為同一套管控在正式環境事故發生時非常危險,這個拉力要先攤開來。

用五條線拆開這題,再處理併發這個真正的技術難點。 這題的存取權限、吞吐量其實不是重點,核心落在預算跟可靠度兩條線上——預算要能擋下超支,可靠度要讓使用者能預期被拒絕之後會發生什麼。技術上最容易被忽略的是併發:如果兩個同時發生的請求各自去讀一次剩餘額度再各自核准,一定會超發。我會用一次性的原子扣減先鎖住額度,擋下第二個請求,等第一個請求真正結算之後再核銷差額、釋放多保留的錢,而不是只做一個即時更新的用量儀表板。

先用小範圍試跑,用對帳準確率跟錯誤拒絕率衡量,而不是只看好不好看。 我會先開放給一組理解拒絕行為的正式環境管理員,而不是一次全面上線,並且分開追蹤每個工作負載的對帳準確率和 false rejection rate——一個漂亮的整體平均數可能蓋住某個關鍵應用被整組擋死的事實,這是我判斷這套控管是不是真的做到「硬性」的依據。

自我核對清單

用這張表檢查你的回答有沒有漏掉關鍵點:

核對項目有提到?
先把「示警」和「硬擋」定義成兩個不同產品,不假設是同一件事
用五條獨立線拆開限制(存取、吞吐量、預算、品質、可靠度),不混為一談
明確處理併發請求搶同一筆資源的競態,不是只畫一個即時圖表
方案用小範圍試跑起步,而不是一次全面上線
成功指標按工作負載分開看,不是只看單一整體平均數
加分:主動講到「保留只是估計值,之後要對帳核銷」這個常被漏講的環節

今日案例

Stripe:同一個 idempotency key 重複送出,回傳第一次的結果,不是再扣一次錢

Stripe 在 2017 年的工程部落格公開說明了 idempotency key 機制:客戶端在請求裡帶一個獨一無二的字串當作 Idempotency-Key,如果因為網路斷線等原因需要重試,用同一個 key 重送,Stripe 會直接回傳第一次請求的結果,而不是再執行一次扣款。這解決的正是今天練習題同一類問題——當一個動作「必須剛好執行一次、不能多也不能少」時,光靠重試機制本身無法保證安全,需要一個獨立的機制先記住這個動作「已經發生過」。Stripe 現行的官方 API 文件在 2026 年仍明文保留這條規則:如果同一個 idempotency key 的請求正在被併發執行、彼此衝突,Stripe 不會儲存這次的冪等結果——這跟今天練習題裡「兩個併發請求不能各自讀到舊的餘額」是同一個底層問題,只是 Stripe 解的是「同一個動作不能重複執行」,練習題解的是「多個動作不能一起超支同一筆預算」。

面試連結:被問「要怎麼保證重試不會造成重複的副作用」時,不少候選人會先想到「加個檢查看看是不是已經做過」,但沒講清楚這個檢查本身要怎麼避免自己也遇到併發的競態。Stripe 的作法示範了正確的收斂點:用一個客戶端產生、伺服器端記錄的唯一鍵,把「檢查」和「記錄」黏成同一個原子動作——這跟今天框架裡的「原子預留」是同一個設計原則,可以直接當成技術 PM 面試裡回答「分散式系統怎麼做到恰好一次」的具體案例。

延伸閱讀

參考資料