我服務的民宿客戶沒有 IT 人員。系統壞掉的時候,他們不會看到監控警告——他們是因為客人沒收到報表才發現出了問題。這是一個很糟糕的方式來發現基礎設施的問題。
去年底,我為幾個民宿業主客戶建了一套 Google Ads 自動化系統,跑在 n8n Queue Mode 上。這套系統應該每週一安靜地跑一次:拉廣告成效數據、生一份報表、送出去。沒有人需要去想它。這就是建它的目的。
實際上,一直在想這件事的人是我——而且太頻繁,通常是在週末。
原本的 n8n 架構長什麼樣
Queue Mode 的 n8n 需要四個容器:主應用、worker、webhook receiver,還有 Postgres。我全部跑在 Railway 上,費用大概是每月 $15–20 美金,對一個客戶專案來說還好,但真正的成本不是錢。
真正的成本是維護時間。每次 n8n 出新版本,就有東西壞掉。Credential 要重新設定,某個 node 的 API 行為改了,Postgres 的連線池又不一樣了。我常常在週日下午花兩個小時在 debug 一個「應該自動跑」的系統。
四個容器,跑一個 cron job,一週一次。
真正讓我下定決心的那次
有一次 n8n 版本升級,悄悄改了某個 node 處理 HTTP Basic Auth 的方式。工作流程在 UI 上看起來跑成功了,但實際的 API call 都在失敗。
我是因為客戶問「怎麼沒收到報表」才發現的。
這句話本身就是問題所在。系統沒有捕捉到失敗——是客戶注意到缺席才發現的。我花了三個小時在 visual editor 裡 debug,試圖找出到底哪裡變了。中間有個念頭閃過:如果這是 Python script,我大可以寫個 unit test,在它碰到任何人之前就抓到這個問題。
GitHub Actions 版本
遷移花了大概一天。現在整個系統就是一個 Python script 加一個 workflow YAML。
name: Google Ads Weekly Report
on:
schedule:
- cron: '0 1 * * 1' # 每週一 09:00 台北時間(UTC+8)
workflow_dispatch:
jobs:
run-report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run Google Ads report
env:
GOOGLE_ADS_DEVELOPER_TOKEN: ${{ secrets.GOOGLE_ADS_DEVELOPER_TOKEN }}
GOOGLE_ADS_CLIENT_ID: ${{ secrets.GOOGLE_ADS_CLIENT_ID }}
GOOGLE_ADS_CLIENT_SECRET: ${{ secrets.GOOGLE_ADS_CLIENT_SECRET }}
GOOGLE_ADS_REFRESH_TOKEN: ${{ secrets.GOOGLE_ADS_REFRESH_TOKEN }}
CUSTOMER_ID: ${{ secrets.CUSTOMER_ID }}
NOTIFY_EMAIL: ${{ secrets.NOTIFY_EMAIL }}
run: python scripts/weekly_report.py
workflow_dispatch 這個 trigger 是我覺得最實用的小細節。不用等到週一,直接在 GitHub UI 上手動觸發,客戶週中臨時想確認什麼的時候很方便。
Credential 全部搬進 GitHub repository secrets,不用再管 n8n 的 credential vault,也不用猜 Railway 的環境變數有沒有正確注入。
真的變好的地方
零常駐費用。 GitHub Actions 私有 repo 的免費額度對一個一個月跑四次的工作綽綽有餘。從每月 $20 美金降到 $0。對服務毛利有限的小型民宿客戶來說,這很重要——我不需要把基礎設施費用轉嫁給客戶。
程式碼進了版本控制。 聽起來理所當然,但在 n8n 裡不是這樣。workflow 存在 Postgres 資料庫裡,要回滾只能從備份還原。現在就是 git revert。出了問題,有清楚的歷史記錄可以追蹤什麼時候改了什麼。
可以在本機測試。 Python script 在我電腦上直接跑。塞進測試用的 credential,看一下輸出,沒問題再 push。這件事在 n8n 的 visual workflow 裡根本做不到。前面說的那個 Auth 靜默失敗,如果是 Python script,本機跑一下就會看到 auth error,上線之前就能修掉。
失敗是可見的。 GitHub Actions 的 job 失敗會立刻發 email 通知。失敗模式從「客戶幾天後注意到報表沒來」變成「我立刻收到通知」。對於在跑著一套沒人盯的自動化系統來說,這是一個實質性的差異。
放棄了什麼
Visual editor 對非工程師確實親切很多。如果有一天要把這個系統交給不會寫程式的人維護,n8n 的 UI 會比 Python script 加 YAML 好上手得多。
另外,n8n 的錯誤處理和重試機制是內建的。換成 GitHub Actions 之後,這些邏輯要自己寫:加 try/except、決定什麼算可重試的錯誤、怎麼發失敗通知。不難,但以前不用想這些。
真正的教訓
問題的核心是工具選擇跟需求不匹配。n8n Queue Mode 是一套認真的系統——它是為需要處理複雜事件驅動流程、多個並行工作流程的團隊設計的。而我用它跑的是:一個 Python script,一週一次。
對於「需要穩定、維護成本低」的每週批次工作,cron job 才是對的工具。不是所有東西都需要常駐服務,而常駐服務的維護開銷,在服務沒有技術背景的小型客戶時會被放大——因為他們的容忍度很低,而問題的能見度很差。
遷移花了一天。那之後的週末,我沒有再在 debug n8n。