免費版資料庫的生存危機:Supabase 閒置暫停機制
作為愛好折騰的開發者,Supabase Free Tier 是部署側邊專案(Side Projects)的絕佳選擇。然而官方有明文規定:若專案連續 7 天沒有活動(Activity),將會自動進入暫停(Pause)狀態。一旦專案被暫停,API 將會回傳 500 系列錯誤,此時必須由開發者登入 Supabase 控制台手動點擊「Resume」,需要等待數分鐘才能恢復運作。
這對於流量不大但需要隨時保持反應的個人工具、電報機器人(Telegram Bot)或 AI 助理來說,簡直是災難。因此,我們需要一套自動化機制,每天幫我們對 Supabase 進行「心跳探測」與「活動模擬」,確保專案永遠維持活躍。
Core Philosophy核心策略:主動寫入(Active Writes) vs. 唯讀 Ping
許多常見的保活方案,是寫一個指令碼每天對資料庫執行 SELECT 1 或唯讀查詢。然而,這種做法在實務上有兩個隱憂:
- 活動定義不明確:雲端平台對於「活動」的判定基準可能隨時調整,唯讀的 API 查詢有時不會被認定為「有效的資料庫使用」。
- 不產生實際指標:單純的讀取對雲端計費和統計報表上的「Write Operations」毫無貢獻。
因此,我的設計哲學是「主動同步、真實寫入」。我們不要無聊的 SELECT,而是讓 n8n 真的去做資料搬移與 AI 處理:每天將真實的外部資料(Notion 筆記、GDrive 文件),經過 Gemini AI 處理後,在 Supabase 向量資料庫(pgvector)中進行「先刪除、後寫入」的同步流程。這不僅創造了無可爭議的寫入活動,還順便幫我們保持了 RAG 知識庫的最新狀態!
如何避免資料膨脹?
主動寫入最大的風險是資料量無限增長,最終爆掉 Supabase Free 的 500MB 儲存限制。因此,我們在寫入前必須先透過 metadata 篩選器精準定位,將前一次寫入的保活資料全部刪除,再寫入新資料。如此一來,資料庫的大小永遠維持在固定範圍,卻能創造出源源不絕的「活動證據」。
實戰工作流一:Notion AI 知識同步保活 (Notion_2_Supabase)
這是我在生產環境運作的工作流之一。它每天定時將 Notion 中的學習卡片、英文單字或 FAQ,透過 Gemini 整理成結構化 Markdown,再同步到 Supabase 的向量資料表中。而且,一條 n8n 工作流可以同時保活 3 個不同的 Supabase 專案!
每天凌晨三點自動啟動,避開流量高峰。
讀取名為 EnglishVocabulary 的 Notion 資料表,每次限制 10 筆。
利用輕量、極速的低成本 Gemini 模型將內容整理成多層級結構的 Markdown。
並行同步至 三個獨立的 Supabase 專案,三個願望一次滿足。
Notion_2_Supabase 工作流邏輯拆解
- Notion 讀取:使用
Get many database pages節點拉取最新卡片。 - AI 格式化:透過
Basic LLM Chain呼叫gemini-2.5-flash-lite,搭配 System Prompt 扮演醫療資訊系統產品經理,將混雜的問答對轉化為標準的 Markdown FAQ,並在結尾插入分隔線。 - 防禦性刪除:在 Supabase 節點設定 Operation 為
Delete,並使用篩選字串=metadata->>embeddingKey=like.faq,將昨天的 FAQ 向量清空。 - 向量化寫入:透過
Vector Store Supabase節點,使用gemini-embedding-001生成嵌入,並寫入目標向量表gemini001中。
實戰工作流二:GDrive PDF 條例向量同步 (renewSupabase)
如果沒有 Notion 資料來源,也可以使用靜態文件保活。此工作流使用 Google Drive 上的政府法規 PDF(例如:管制藥品管理條例.pdf),定期重新切割、向量化,並同步至 4 個 Supabase 實例。
每週執行三次,預留充足的暫停緩衝期。
自動下載指定的法規 PDF 檔案並提取純文字內容。
設定 chunk size 與 overlap,將 PDF 切割成適當大小的語意區塊。
一次運作,同時喚醒 多個不同的 Supabase 資料庫專案。
renewSupabase 工作流邏輯拆解
- 排程與參數設定:設定每週定時啟動,並透過
Set節點將目標向量表名稱統一指定為renew_supabase_768。 - 下載與解析 PDF:使用
Google Drive節點下載 PDF 檔案,並透過Extract from File提取為純文字。 - 多資料庫防禦性刪除:對 4 個 Supabase 連線,同時發起 Delete 請求,利用篩選器
=metadata->>testKey=like.abc123刪除前次保活產生的向量。 - 向量嵌入插入:使用
Embeddings Google Gemini節點,結合models/gemini-embedding-001,將切分後的 PDF 文件重新 Insert 到 4 個資料庫中。
進階軟體工程思維:防禦性設計與狀態一致性
在 n8n 畫布上拉出流程很簡單,但在生產環境中保持穩定且不搞砸資料庫,需要嚴謹的工程設計。這兩個工作流融入了以下防禦性設計理念:
1. 競態條件與順序控制(Order Control)
n8n 預設會盡可能並行執行節點。如果我們在刪除舊資料的同時寫入新資料,可能會發生「新資料先寫入,舊資料後刪除」的競態條件(Race Condition),導致資料庫最後空無一物,或者資料重複累積。為了實現絕對的狀態一致性:
- Aggregate 節點阻擋:我們在 Delete 節點後方放置了
Aggregate節點。它扮演了「柵欄(Barrier)」的角色,會強行等待所有 Delete 請求完全響應並合併資料後,才允許工作流往下游走。 - Wait 節點緩衝:在進入 Insert 寫入節點前,加入 3 秒的
Wait節點,確保 Supabase 內部索引更新完畢,避免瞬時的高頻存取被 Supabase 的 rate-limit 拒絕。
2. 告警邊界與防禦性分支(Error Output Handling)
當我們用單一工作流管理多個資料庫時,最怕其中一個資料庫暫停或憑證過期,導致整條工作流中斷,進而讓其他健康的資料庫也無法保活。我們的對策是:
- 開啟 Supabase 節點的
onError: "continueErrorOutput"設定。 - 當
AS-Jira執行 Delete 失敗時,它不會讓工作流崩潰,裝作什麼都沒發生,而是會將錯誤資訊導向 Error 輸出分支,觸發Telegram Node發送警報(例如:Ping Supabase AICS error),同時主線流程依然可以順利走完其他三個資料庫的保活。
| 設定項目 | 設定值 / 策略 | 工程考量 |
|---|---|---|
| Delete Filter | metadata->>testKey = abc123 (或 faq) |
防止誤刪生產環境中的真實業務資料。 |
| Credentials | n8n Encrypted Credentials | API Key 絕不寫死在代碼或 node parameters,避免隨 JSON 匯出外洩。 |
| Error Mode | Continue Write (Error Output) | 避免單一資料庫停機引發連鎖崩潰。 |
| Control Flow | Aggregate + Wait (3s) | 確保「先刪除、後寫入」的嚴格順序,並防止 Rate Limit。 |
測試、告警與維護計畫
保活系統必須是「可觀測的(Observable)」。我們不希望它默默死掉,等到 Supabase 被暫停了才發現。
1. 製造一次防禦性失敗
在設定好 Telegram 告警後,你可以手動將 Delete 節點的表名修改為不存在的表,執行一次工作流,確認 Telegram 群組能夠即時收到帶有錯誤原因與時間戳記的告警訊息。確認無誤後,立刻將表名還原。
2. 設定 n8n 執行歷史保留期
請確保你的自託管(Self-hosted)n8n 實例或雲端版,將 Execution History 的保留期設定為至少 7 天(建議 14 天)。如此一來,你可以隨時點開歷史紀錄,確認最近一週內每天都有綠色的成功勾勾,作為 Supabase 確實有被活動保活的歷史證據。