[已讀亂回] GAS + N8N + Notion + Sheet 的架構選型

2026-05-26 · 5,835 字 · 14 分鐘

前陣子在某個 Facebook 技術社團看到一篇貼文,作者分享他幫某非營利宗教組織設計系統的選型過程。元件組合是 GAS(Google Apps Script)+ N8N + Notion + Google Sheet,每個工具都被指派了一個角色。

那篇文章蠻短的,看完之後我順手把這套 stack 在腦袋裡跑了一遍 — 想看看自己會怎麼還原它的架構、推導出哪些設計細節、最後跟我自己的習慣解法差在哪。

這篇是把那段腦袋裡的過程攤平寫下來的紀錄。會經過幾個階段:還原原文的架構、選一個假設版本、做幾輪結構觀察、補上量化驗證、最後對照業界常見的選擇。

原文摘錄

來源:Facebook 社團貼文

每次選技術架構都是一場取捨,這次分享我幫非營利宗教組織設計系統時的思考過程。

使用者是非技術背景的全職人員,所以第一個限制是「不能要求安裝任何東西」。Google Apps Script 直接在瀏覽器跑,部署即網頁,完美符合。

N8N 自架在 Zeabur,解決了兩個問題:一是視覺化流程讓每個 Webhook 獨立管理,維護容易;二是長期運行不依賴個人電腦,不怕有人關機。

Notion 最聰明的地方在於它同時是資料庫和後台管理介面。主管想調整員工權限?進 Notion 打個 checkbox 就好,完全不需要動程式碼。

Google Sheet 當備援,Notion 掛掉時資料繼續寫得進去,系統不中斷。

選工具的邏輯:

  • GAS — 免費、免安裝、直接是網頁
  • N8N — 視覺化流程、自架、長期穩定運行
  • Notion — 資料庫兼後台,打 checkbox 調權限
  • Google Sheet — 備援,Notion 掛了繼續跑

每個工具都有它的位置,沒有多餘的。 每個工具都有它存在的理由,沒有多餘的,也沒有缺少的。

這種「剛好夠用」的架構設計,你覺得有什麼優缺點?

還原原文的架構

要先說一件事:原文沒有附架構圖,下面所有架構圖都是我從文字推出來的猜想。我會列出幾個可能的讀法、用原文線索挑一個比較接近原作者意圖的版本,作為後續分析的對象。並不保證這個拆解跟作者腦袋裡的版本完全一致 — 但即使猜錯,後面挖出來的那幾個結構問題大致都還會存在,只是會落在不同的位置。

原文的關鍵句:「使用者是非技術背景的全職人員,所以第一個限制是『不能要求安裝任何東西』」。從這句出發,整個 stack 被組裝成這樣:

問題來了:原文沒有直接畫架構圖,這四個工具實際上怎麼串起來其實有歧義。我試著畫了兩種可能的讀法。

架構 A:N8N 中央編排 hub

GAS 是薄殼、所有寫入都過 N8N。

[ Staff ]                                     [ Manager ]
    |                                              |
    | open web                                     | tick checkbox
    v                                              v
+-------+     webhook      +-----------------+  +-----------+
|  GAS  | ---------------> |       N8N       |  |  Notion   |
| (thin)|                  | validate/route  |  |  (DB+UI)  |
+-------+                  +--------+--------+  +-----+-----+
                                    |                 ^
                                    | read perm/write |
                                    +-----------------+
                                    |
                                    | Notion down
                                    v
                           +-----------------+
                           |  Google Sheet   |
                           |    (backup)     |
                           +-----------------+

架構 B:N8N 旁側自動化

GAS 直接 CRUD Notion,N8N 只處理排程通知、跨系統整合。

[ Staff ]                                  [ Manager ]
    |                                           |
    | CRUD on web                               | tick checkbox
    v                                           v
+-------+   Notion API    +-----------------+
|  GAS  | <-------------> |     Notion      | <-- Manager edits
+-------+                 |  (DB + admin)   |
                          +--------+--------+
                                   ^
                                   | schedule / notify
                                   |
                          +--------+--------+
                          |  N8N (Zeabur)   |
                          |    sidecar      |
                          +-----------------+

三條線索消弭歧義

回到原文逐句檢查,三處線索把指針推向 A:

第一,「視覺化流程讓每個 Webhook 獨立管理、維護容易」這組詞只有在 business logic 真的住在 flow 裡時才有意義。旁側自動化的維護頻率很低,不會被當成主要賣點。

第二,「Notion 掛掉時資料繼續寫得進去」要做到透明 fallback,必須有一個編排層在中間 route。架構 B 的 GAS 直接 CRUD 沒法做這件事,得拉一個編排層出來。

第三,四個工具的描述呈現「一條 pipeline」的節奏,不是「並排各自獨立」。

OK,A 比 B 更貼近原文意圖。但 A 還不夠精細,要繼續往下挑一個能完整撐起原文承諾的版本。

從多組讀法中挑選假設架構

A 還不夠細,主要是把「讀」這條路徑當沒看到。把使用者打開網頁的常見動作攤開來看:報名表單、列表查詢、編輯紀錄。讀的次數遠多於寫,而且讀通常需要即時回應。

如果讀也走 N8N,每個查詢都要拉一條 flow,N8N 的「視覺化好維護」反而變成負擔 — flow 數量會跟著情境膨脹。比較合理的拆法是讀寫分離。

架構 C:讀寫分離

讀直接打 Notion、寫過 N8N。

[ Staff ]                                       [ Manager ]
    |                                                |
    | open web                                       | tick checkbox
    v                                                v
+--------+   read: direct Notion API   +-------------+
|        | <-------------------------> |   Notion    | <-- Manager edits
|  GAS   |                             |  (DB + UI)  |
|        |   write: webhook             +------+------+
+----+---+                                     ^
     |                                         |
     v                                         | read perm / write
+----+--------+                                |
|     N8N     | -------------------------------+
|  (Zeabur)   |
+------+------+
       |
       | Notion down
       v
+------+--------+
| Google Sheet  |
|   (backup)    |
+---------------+

但 C 有個問題 — Notion 掛了的時候,寫得進去、讀不出來。

寫入這條:Notion 掛了 → N8N 改寫 Sheet → 那筆資料安全進去 Sheet。但讀取這條:GAS 還是直直打 Notion → Notion 掛了 → 看不到剛剛寫進去的那筆。N8N 知道 Notion 掛了、自動改了寫入目標;GAS 不知道,照樣去找 Notion。兩邊看到的世界不一樣,使用者可能剛送出表單、馬上回頭刷新就找不到。

要補這個洞有兩條路。

第一條路是寫入改成 dual-write — 永遠雙寫。不切換,N8N 收到 webhook 就 parallel 寫 Notion 跟 Sheet。Notion 永遠是即時的,GAS 直讀 Notion 永遠對。

第二條路是讀也走 N8N — 統一判斷誰活著。GAS 退化成純前端,所有資料流都過 N8N。但 N8N 本來是視覺化 workflow 工具、不是高效能 API gateway,讓它扛所有讀請求是 stress 它的設計目的。

我選第一條,再補上一個讀取 fallback(Notion 掛了 GAS 改讀 Sheet)。後續用這個假設架構當分析對象。

假設架構 C''

                                       [ Manager ]
                                            |
                                            | tick checkbox (bypass)
                                            v
                                       +-----------+
[ Staff ]           read 1: primary    |  Notion   |
    |          +------------------->   | (DB + UI) |
    v          |                       +-----+-----+
+--------+     |                             ^
|        |-----+                             |
|        |                                   | (a) parallel write
|  GAS   |                                   |
|        |--webhook-->  +-----+--------------+
|        |              | N8N |
|        |              +-----+--------------+
+--------+                                   | (b) parallel write
    |                                        v
    |          read 2: fallback         +----+---------+
    +--------------------------------->| Google Sheet  |
                                       | (live mirror) |
                                       +---------------+

讀寫分離、dual-write、讀取 fallback — 這版寫進去的東西讀得到、讀寫看到同一個世界,能撐起原文「系統不中斷」這個承諾。接下來對它做幾輪壓力測試。

結構壓力測試(質性)

假設架構大致定了。接下來看看這個結構在不同情境下會冒出什麼問題。

dual-write 的 partial failure

parallel 寫兩邊,意味著要面對四種狀態:

N8N flow 必須回答這四個狀態各自要怎麼處理:回 200 還是 4xx?要不要 retry?要不要告警?這個邏輯拉得出來,但拉得出來不代表簡單。

Notion 復原後的回填難題

更深的問題在恢復階段 — Notion 掛了 Sheet 接下所有寫入(或者 dual-write 寫不進 Notion)、可是 Notion 復原之後,那段時間 Sheet 收進來的資料怎麼回到 Notion?

三條設計選項,每條都有隱藏成本:

選項 機制 隱藏成本
自動回填 偵測 Notion 復原 → 跑 job 把 Sheet 缺漏寫回 健康偵測(不能只看一次成功)、找出缺漏(時間戳?status flag?)、Notion rate limit 下回填速度、Manager 同時編輯的 race、idempotent 需求
唯讀模式 + 手動 偵測異常 → 切到 reject write、return「系統暫時唯讀」→ 人工確認補完 使用者體驗坦白降級、N8N 需要 circuit breaker、需要 oncall 與 SOP、「人工」對非營利的可持續性是問題
接受 diverge 不回填、Sheet 永遠完整、Notion 永遠缺一段 後台失真、權限決策基於不完整資料、Notion 慢慢變成「只是個 UI 殼」

備援的故事在「寫入不會斷」這段聽起來很美,可是一接到「復原之後呢?」這個問題就會發現是個沒被處理的角落。三條路每一條都不便宜。

Notion 三重身份的可用性集中

Notion 在這個架構中身兼三職:資料庫、後台管理介面、權限資料源。三件事被同一個 SaaS 服務承擔,意味著它一掛、三件事一起掛。

具體說:

Sheet 補上其中一件(資料層),另外兩件還是綁死在 Notion 身上。「Notion 掛了系統不中斷」這句話的範圍其實沒有那麼廣。

「不能安裝任何東西」的真正邊界

原文的設計起點是「不能要求安裝任何東西」。仔細想:這個約束的範圍只在使用者端。

把整個 stack 的「安裝行為」攤開:

User side                          Operator side (the author)
   |                                    |
   v                                    v
[ Browser ]                        [ Zeabur account + paid plan ]
   |                                    |
   v                                    v
open GAS web app                   self-host N8N container
   |                                    |
   v                                    v
open Notion / Sheet                upgrades / monitor / downtime
   |                                    |
   v                                    v
zero install                       heavy install + ongoing ops

GAS、Notion、Sheet 都是 SaaS、零維運。N8N 才是這個 stack 裡最違反「零安裝」精神的元件 — 要安裝、付費、升級、監控、處理當機。

「零安裝」這個賣點被擴大解釋成整個 stack 的屬性,可是實際上它只是「把安裝負擔從使用者端轉移到雲端」。任何系統都需要有人維運,這點原架構並不特別;只是這份負擔具體落在哪、未來交接的成本是什麼,後面結論會再回來算一次。

量化驗證

質性觀察可以再用數字驗一次。挑各元件的可用性、組合起來、再看看 rate limit 對 throughput 的影響。

各元件每月可用性

數字是估計、不是合約 SLA:

元件 估計
GAS ~99.9%
N8N(Zeabur 自架) ~99% 樂觀
Notion ~99.5%
Google Sheet ~99.9%

組合可用性的三種狀態

系統可分三種運作狀態,每種需要的元件不同:

如果 N8N 含維運失誤實際只有 98%,完全運作可用性掉到 ~97.3%、每月 ~19.5 小時 downtime。

關鍵發現:N8N 自架是整個架構的可用性瓶頸 — SaaS 元件再高可用,自架那塊會把總體拉低。實務上這份 downtime 可以靠維運排程(夜間升級、週末維護)吸收掉一大部分,使用者多半在工作時段操作的內部系統,感受不會像數字看起來那麼嚴重。

Notion API 3 req/s 的吞吐天花板

可用性是時間維度的限制,rate limit 是流量維度的限制。Notion 的 3 req/s 是最緊的那個。

每筆使用者寫入觸發的 API call:

1 user write ->
   GAS  -> N8N                    (N8N itself unlimited)
   N8N  -> Notion: read perm      (1 req)
   N8N  -> Notion: write record   (1 req)
   N8N  -> Sheet:  write mirror   (1 req)
   = Notion: 2 reqs total, Sheet: 1 req total

寫入吞吐天花板 ≈ 90 筆/分鐘。

對日常使用 OK,但任何「同時段事件」(活動報名、月初繳費)會立刻撞牆。100 人同一分鐘報名 = 200 個 Notion req/min ≈ 3.3 req/s、撐不住。撞牆後 N8N 開始 retry 或 queue,使用者看到延遲或失敗。

更微妙的是:失敗 fallback 到 Sheet 不會緩解,因為瓶頸在 Notion 那邊 — 連權限都讀不過去。

Notion 三重身份不只是可用性風險集中,throughput 也是壓力集中點。

整合測試的隱性負擔

到目前為止講的問題(dual-write 的 partial failure、Notion 掛了的 fallback、權限傳播時機)每一個都需要對應的測試。沒有測試保障,這套架構的承諾就只是口號。

問題是:multi-service 架構的測試難度不是線性增加、是組合爆炸。

每個外部服務各有它的測試困境:

「Notion 掛了系統不中斷」這句話要驗證,得能跑這 7 個失敗路徑情境:

# 情境
1 happy path:寫 Notion ✅、寫 Sheet ✅
2 Notion 寫失敗、Sheet 成功 → N8N flow 怎麼回應?
3 Sheet 寫失敗、Notion 成功 → 對帳機制?
4 兩邊都失敗 → 使用者畫面顯示什麼?資料丟了嗎?
5 Notion 讀失敗、GAS fallback Sheet → 觸發條件是 timeout 還是 error code?
6 權限讀失敗(Notion 掛時 N8N 嘗試讀) → 降級拒絕、cache、還是 fallback Sheet?
7 Manager 改了權限的傳播時機 → 多久內 N8N 寫入會讀到?

要可靠地測這 7 個情境,需要能人為製造每個服務的失敗(攔截 outbound HTTPS?wireshark?mock layer?),需要能對 N8N flow 做 input / output 斷言,需要跨服務追蹤 trace。

這套測試基礎建設本身就是個專案。對非營利組織來說,做不做得起來是另一個問題 — 而沒有這套基礎建設,前面所有的「系統不中斷」承諾就沒有驗證機制。

對照組:經典三層架構

到這裡累積了不少結構代價:dual-write 的 partial failure、Notion 復原回填、三重身份集中、零安裝邊界、可用性瓶頸、rate limit 撞牆、測試矩陣組合爆炸。每一塊都不是無解,但解都不便宜。

退一步想:如果這套 stack 的訴求只是「讓非技術使用者可以填表單、看資料、Manager 可以管理權限」,業界長年的預設答案其實是另一套 — 經典三層架構。

frontend → backend api → stateful data (database)

具體一點:

[ Staff ]                                    [ Manager ]
    |                                             |
    | open web + Google auth                      | open admin + Google auth
    v                                             v
+----------------------------------+
|        Web App (frontend)        |
|  forms / list / edit / admin UI  |
+--------------+-------------------+
               |
               | HTTPS / JWT
               v
+--------------+-------------------+
|   Backend API (self-host)        |
|  business logic / perm / CRUD    |
+--------------+-------------------+
               |
               | SQL
               v
+--------------+-------------------+
|     Postgres (Zeabur addon)      |
|  transaction / backup built-in   |
+----------------------------------+

部署仍在 Zeabur(跟原架構同樣的自架前提)。前端的 Google auth 是一行 OAuth 重導向、不是核心。

moving parts 對比

原架構(C'') 經典三層
主要元件 4 個 + 多條同步線 3 層、單向資料流
資料層 Notion + Sheet + 同步 一個 Postgres + 自帶 backup
寫入路徑 dual-write + partial failure 處理 單寫 + DB transaction
讀取路徑 首選 Notion / fallback Sheet 直讀
權限管理 Notion checkbox(被 Notion 可用性綁定) 標準 RBAC

哪些原架構的成本在三層下消失

複雜度沒消失,是「不該存在的複雜度根本沒被引入」。

三層架構不是免費午餐

當然,這條路有它的代價:要寫程式(不是拉 flow)、開發初期成本高一點、維運仍然要懂 backend 與 DB。

但反過來看:原架構也要懂 N8N、懂 Notion API quirks、懂 Sheet quota、懂 partial failure 處理、懂 rate limit。自架的代價本來就要付,差別只在「換來的是 visual flow,還是換來經典 backend」。

適用條件是「有工程師能持續維運」— 跟原架構自架 N8N 是同等前提。如果完全沒人懂程式、沒人維運,那其實該選的是純 SaaS 工具(Zapier、Make、Airtable、Glide),完全不要自架。

換個角度看 — 可以在 Local 完整跑起來的三層式架構,在 AI Agent 普及之後其實是一份相當好的午餐。

整套系統能在本機啟動、有完整的測試環境,AI Agent 就可以接手整個開發迴圈:寫 feature、跑測試、看 log、debug、再跑一次、commit,整輪可以自動跑。對比原架構,N8N flow 編輯、Notion schema 調整、跨 SaaS 整合測試這些事情,AI Agent 沒辦法接過去自己迭代 — 每一步都要人工打開不同服務的 UI 點來點去,開發迴圈在這裡接不起來。

「要寫程式」這個門檻在 AI Agent 普及之後降低不少。工程師的工作往「定義介面、code review、把關 merge」收,逐行打字、跑測試、改 bug 這類重複性循環交給 Agent。三層 + Local,剛好是這套新開發模式最會的場域。

結論

質性觀察、量化指標、整合測試難度,前面三個維度的審視,最後可以收成一個簡單的選擇題:要不要繼續用 GAS + N8N + Notion + Sheet 這套組合?

兩條合理的路徑都成立,差別在於把複雜度放在哪裡:

如果是我負責設計 + 實作這套系統的完整交付,會選後者。

想像一下使用者拿到的部署手冊長什麼樣。

經典三層版本:一行 docker compose up,前端、後端、資料庫一起啟動;連備份還原都可以寫在同一份 compose 設定裡,使用者按一個指令就執行。

未來要從 Zeabur 搬到別的 VPS 或 VM、或維運責任要轉手給其他人,也都只是把 container image + 一份 SQL dump 交出去而已。

對比之下,原架構的交付手冊大概要這樣寫:

一堆畫面截圖、一堆要點開的設定面板。備份也類似 — 要嘛附截圖教使用者打開每個服務匯出資料、要嘛另外寫一個備份工具給他用。

還有一件事是 scale。經典三層流量上來要加機器、加 DB replica、甚至換更大的 VPS,都是自己掌握的選項。

原架構依賴 Notion,3 req/s 是寫死在 SaaS 端的天花板,沒辦法臨時決定要放寬。受限的不只是當前的吞吐天花板,而是「需要時能不能自己調整」這件能力本身。

至於「為什麼不用視覺化編排省事一點」 — 既然已經接受「需要工程師長期維運」這個前提(不然 Zeabur 上的 N8N 也維運不下去),那把工程師的能力直接拿來寫經典三層,整體結構更乾淨、隱性成本更少、測試更可控。

順著這個方向再多想一步:Notion 在這套架構裡身兼 DB、admin UI、權限源三職,但每件事都不是它原本的設計目的。

具體看三個限制:3 req/s 的 rate limit 從量化分析看是最緊的天花板;資料多了 page 載入會明顯變慢,這是用過大型 Notion database 的常見體感;可用性又跟 Notion 服務本身綁死。

如果 Manager 在這套系統的需求單純就是「打 checkbox 調權限」,那刻一個簡單的 admin 頁面 vibe-code 半小時就完成了,沒 Notion 也行 — 換來的是穩定的延遲、可預期的可用性、權限資料留在自己手上。

每次面對這種選型,我自己會先問兩個問題:一是這個複雜度有沒有換到等量的好處;二是這個選擇主要的風險是什麼、我願不願意為了好處承擔它。這兩個問題拿去評估自己手上的設計也適用。

純粹結構觀察,給有興趣的人參考。