Skip to content

Orbital Express 的起源故事

作者:Jonathan Chen,Orbital Express 創始人


我從 2006 年開始寫程式——超過 20 年的時間,建造東西、搞壞東西,偶爾點火然後看著它燒起來。

我在馬里蘭大學念電腦科學,以全班第一名畢業,後來進入史丹佛大學商學院。2013 年,我共同創立了 FiscalNote——一家政府數據與 AI 公司。我在那裡擔任 CTO,負責建立並領導工程組織將近十年。

Orbital Express 就是我在 FiscalNote 所有犯錯的直接產物。


我犯了什麼錯

FiscalNote 成長很快。我們招人很快。工程師帶著強烈的主見加入,按自己的方式建東西,然後離開。下一批工程師看著前一批留下的東西,心想「這是什麼鬼?」——然後按自己的方式重寫。然後他們也走了。

這個循環有個名字:委員會式義大利麵條程式碼。每個碰過程式碼庫的工程師都在上面留下了自己的指紋。有些指紋是出於好意的壞決策。有些是被後來更差的決策埋沒的好決策。全部累積成一個越來越難以修改的程式碼庫。

我們最糟的時候,一年只能交付四個功能。這些決策讓我在十年間損失超過 一千萬美元。不是來自單一的災難性失敗——而是緩慢、持續的消耗。工程師薪資養著一支動不了的團隊。重寫專案花了六個月,交付的卻是我們本來就有的東西。因為深陷救火而永遠沒有機會開發的功能,所帶來的機會成本。每年數百萬美元,年復一年,都花在了當時看起來合理的糟糕架構決策所造成的後果上。

轉折點是我退一步,意識到自己對「擴展」的思考方式完全錯了。我執著於技術擴展——如何處理更多請求、如何分散負載、如何處理更多數據。與此同時,真正的擴展問題就擺在我眼前:。工程師怎麼入職?一個新人多快能做出真正的貢獻?一個新員工在第一個月能真正理解多少程式碼?

我做過的每一個糟糕架構決策,都因同一個原因而糟糕:它讓個別工程師更快,卻讓整個團隊更慢。微服務讓建它的工程師感到充滿力量。TypeScript 讓引入它的工程師感到滿足。自訂的 build pipeline 讓設計它的人感到聰明。這些東西的每一個,都讓下一個新員工的第一週更難熬。

做出這些決策的工程師不是壞工程師。他們只是在為錯誤的事情優化。


沒人談的招聘問題

當我們使用 Ruby on Rails 時,我們需要 Rails 工程師。我們在華盛頓特區。我把能招到的 Rails 工程師招完了。不是因為 Rails 開發者不存在——他們存在——而是因為我們把自己過濾進了一個死角。

這讓我學到了一件根本性的事:你的技術棧是一個招聘決策。你選擇的每個 framework、語言和模式,都在擴大或縮小你潛在工程師的人才庫。棧越特殊,招人越難,入職時間越長,你就越依賴那些了解這個棧的特定人選——這給了他們籌碼,給了你脆弱性。

正確的問題不是「什麼是最好的技術?」而是「什麼技術讓我能招到最多工程師、讓他們最快做出貢獻、讓程式碼庫保持最長時間的可讀性?」

JavaScript 三項都符合。它是地球上被最廣泛了解的程式語言。如果有人說他會寫程式,他懂 JavaScript 的可能性很高。你篩選的不是稀有技能——而是普遍技能。


微服務陷阱

在某個時間點,FiscalNote 的一位聰明工程師提出了採用微服務的理由。論點很有說服力:獨立部署、獨立擴展、團隊自主運作。我們就這麼做了。

最終我們有了 17 個服務。有些是 Node.js。有些是 Python。有一個是 Go。它們有不同的 logging 規範、不同的錯誤格式、不同的部署 pipeline。讓新工程師入職,意味著解釋的不是一個程式碼庫,而是整個生態系。

在 production 環境除錯,需要跨三個服務追蹤一個 request,才能找出是哪個服務出了問題。當某個東西掛掉,搞清楚為什麼本身就是一場事故。

建立那些服務的工程師都走了。繼承它們的工程師,花在理解架構上的時間比交付功能還多。

微服務是一個以技術方案偽裝的組織問題解法。 它為 Netflix 這樣的公司而設計——他們有數百位工程師在真正獨立的領域工作,協調部署的成本超過了運營複雜度的成本。對一家 15 人的新創公司來說,這個取捨完全顛倒。你沒有足夠的工程資源來運營基礎設施,你的領域也沒有獨立到足以justify這種分割。

從 monolith 開始。在它真的讓你痛苦之前繼續用它。大多數公司永遠到不了真正讓人痛苦的那一步。


凌晨兩點的電話

在微服務複雜度之上,我們把所有東西都跑在 AWS 上。數十個服務、手動基礎設施配置、自訂部署 pipeline、VPC 網路、IAM 政策、負載平衡器——一應俱全。當時感覺是個專業的選擇。

它實際上產生的,是一支 DevOps 團隊定期在凌晨兩點醒來救火。不是偶爾——而是定期。我們有人的整個工作就是管理基礎設施,但他們還是會在半夜被叫醒。系統太複雜,無法做到可靠;太客製化,沒有任何一個人能完全理解。當某個東西壞掉,它會以需要數小時追蹤的方式壞掉。

成本是真實的:一支薪資存在純粹為了管理我們自己強加給自己的基礎設施稅的團隊。即使有了這支團隊,我們還是有停機、還是有部署失敗、還是有某個服務以沒人預料到的方式掛掉而毀掉某人週末的夜晚。

當我創立 Nitra 並在 Orbital Express 上建構時,我做了不同的決定:部署用 Heroku,服務用 Redis Cloud 和 Render。託管基礎設施。沒有 DevOps 團隊。沒有自訂 pipeline。沒有凌晨兩點的電話。

在 Nitra 超過五年的時間裡,我們有 起部署救火事件。零。不是「更少」——是零。基礎設施就是能跑。當我想部署,我 push 程式碼。這就是整個流程。原本要花在 DevOps 團隊、on-call 輪值、事後檢討上的時間——全部拿去開發功能了。

AWS 很強大。它同時也是一個巨大的運營負擔,大多數新創公司根本沒有必要承擔。今天可用的託管服務——Heroku、Render、Railway——是生產級、可靠的,成本也只是 AWS 所需工程時間的一小部分。你用一些理論上的客製化彈性上限,換來了實際運營理智的下限。對絕大多數產品來說,這個交換顯然是正確的。

不要僱用 DevOps 團隊。不要自己管理基礎設施。去交付功能。


結果

我離開 FiscalNote,創立了 Nitra。我從頭建起 Orbital Express,把我學到的一切——每個壞決策、每段入職噩夢、每個凌晨兩點追蹤微服務的除錯時光——全部反過來。

最大主見。最少魔法。一種語言。一個部署目標。每件事都有一個統一的模式。

第一次認真使用 Orbital Express,我們每週交付四個功能。同樣規模的團隊。更好的產品品質。更少的壓力。

唯一的差別是 framework。


這個 framework 真正是為了什麼

Orbital Express 不是在試圖成為技術上最令人印象深刻的 framework。它不是在爭基準測試排名,也不是在支援每一種可能的使用案例。它只想做一件事:讓你快速建出一個 production API,讓它在多年後依然可維護,並在不需要一個月的知識交接的情況下移交給任何工程師。

烙印在這個 framework 裡的主見並非任意為之。它們是 FiscalNote 每一個拖慢我們的決策的直接反面:

  • Feature folder 而不是按類型分資料夾——因為當你在修 "Orders" 的 bug 時,你希望所有訂單相關程式碼都在同一個地方,而不是分散在 models/、controllers/、routes/、tests/ 各處。
  • 一種語言(純 JavaScript)——因為入職應該是幾天,不是幾個月。
  • 沒有微服務——因為一個你能理解的 monolith,勝過一個你搞不懂的分散式系統。
  • 託管部署(Heroku/Render)——因為工程師應該在開發功能,而不是在配置 VPC。
  • Generator 優於樣板——因為最常見的入職錯誤是把東西寫得略有偏差;generator 讓這件事變得不可能。

每一個規範都有理由。每一個主見都是付過代價換來的。


關於 AI 與這個 framework 的一點說明

我們活在一個 AI 寫程式碼的世界裡。這讓天平更進一步倒向簡單性。

在網路上訓練的大型語言模型,對 JavaScript 的了解勝過任何其他語言。它了解 Express。它了解 Sequelize。當你要求它在 Orbital Express 中開發一個功能時,規範如此一致、如此標準,AI 可以可靠地遵循它們。

TypeScript 的型別讓 AI 助手困惑。自訂的 build 系統讓它們困惑。特異的模式讓它們困惑。簡單、一致、文件完善的 JavaScript 不會。

如果說過去十年是關於讓工程師更快,那麼下一個十年是關於讓 AI 更快。答案是一樣的:保持簡單,保持一致,保持可理解。


如果這些話引起了你的共鳴——如果你被同樣的決策灼傷過——這個 framework 是為你而建的。

— Jonathan Chen (@Hackbyrd)