備份、升級與上線檢查:自架 Supabase 的維運三支柱 | Supabase 完整教學
上一篇我們用 Docker Compose 把整套 Supabase 自架(self-hosting)跑了起來、成功登入 Studio——但那只是「架起來」。這一篇要補上自架最硬、也最容易被忽略的維運三支柱:備份、升級、上線檢查。你會學到怎麼用
pg_dump做每日邏輯備份、用 WAL-G 實作 PITR 任意秒數還原,怎麼真正跑一次還原演練(而不是假設備份會動),雲端與自架各自該怎麼安全升級版本,以及一份上線前逐項打勾的生產環境檢查清單與災難復原流程。記住那句自架的鐵律:沒有測試過還原的備份,等同於沒有備份。 這是自架段(SB-5)的第二篇。
前言
先用一句話定義本篇的主題:維運,就是讓一套已經跑起來的自架 Supabase「跑得久、還原得回來、升級不出事」的那些日常工作。 上一篇《自架部署(Docker Compose)》教你把服務架起來、登入 Studio;但架起來只是第一天,真正的挑戰是接下來的每一天——資料會壞、伺服器會掛、版本會過時,而自架版沒有雲端幫你托管的自動備份與 PITR,這些全部得你自己扛。
用一個類比理解「自架的維運」是什麼。如果說雲端 Supabase 像租屋,房東幫你保了火險、定期檢查水電、出事有人負責;那自架就是自己買房——房子是你的,但火險要自己保、消防演習要自己做、瓦斯漏了要自己修。 備份就是你的火險,還原演練就是消防演習,上線檢查清單就是入住前的驗屋單。這三件事平常看不出價值,但少了任何一項,某一天資料庫崩了、伺服器炸了,你就會付出慘痛代價。
也因此,這一篇的心態和前一篇不同:前一篇談「怎麼把東西做出來」,這一篇談「怎麼確保東西不會在最糟的時刻背叛你」。維運的核心不是樂觀,而是假設一切都會壞,然後預先準備好復原的路。
本篇你會學到:
- 備份策略:
pg_dump邏輯備份 vsWAL-G的 PITR 物理備份,以及雲端自動備份與自架自理的差別 - 還原演練:怎麼跑一次真正的
pg_restore,把「有沒有備份」變成「還原得回來」 - 版本升級流程:雲端 Dashboard 一鍵升 vs 自架自己拉 image、
recreate容器的安全順序 - 上線前檢查清單:金鑰、RLS 全開、SMTP、資源與連線、備份、監控——一份能逐項打勾的驗收單,外加災難復原(DR)的思路
本篇聚焦「維運」這件事——備份、還原、升級、上線檢查。自架的映像版本、環境變數名稱、升級步驟都可能隨 Supabase 版本演進而變動,正式導入前一律以官方文件與 release notes 為準;雲端方案的備份層級(每日備份、PITR 保留天數)則以官方定價頁與 Dashboard 當下顯示為準。
核心概念
在動手寫備份腳本之前,先建立三張心智圖:一是「備份有哪幾種、各自的還原粒度是什麼」,二是「升級在雲端與自架是兩件完全不同的事」,三是「上線前該檢查哪些面向」。
一、備份策略:邏輯備份 vs 物理備份 + PITR
自架 Supabase 沒有內建的自動備份機制。這一點必須先講清楚:你在雲端 Dashboard 看到的「每日自動備份」「Point-in-Time Recovery」,是雲端付費方案(Pro 以上)才有的托管功能,自架版一律沒有,得自己規劃。備份的主流做法有三種:
| 策略 | 工具 | 還原粒度 | 複雜度 |
|---|---|---|---|
| 邏輯備份 | pg_dump / pg_restore | 每次備份的時間點 | 低 |
| 物理備份 + WAL 歸檔 | WAL-G + S3 | 任意秒數(PITR) | 中高 |
| 第三方託管 | SimpleBackups、Pigsty 等 | 視方案而定 | 低 |
理解這張表的關鍵,是搞懂**「邏輯備份」與「物理備份」的差別**:
- 邏輯備份(
pg_dump):把資料庫的內容「dump」成一份可重放的 SQL 或壓縮檔。它記錄的是「這一刻資料長什麼樣」,像幫資料庫拍一張快照照片。優點是簡單、可攜(能還原到不同版本的 PostgreSQL)、還原直觀;缺點是還原粒度只能回到「上一次備份的時間點」——如果你凌晨兩點備份、下午三點出事,凌晨兩點到下午三點之間的所有變更都救不回來。 - 物理備份 + WAL 歸檔(
WAL-G):除了定期做「base backup」(完整的資料目錄快照),還持續把 PostgreSQL 的 WAL(Write-Ahead Log,預寫式日誌) 歸檔到 S3。因為 WAL 記錄了每一筆變更,還原時可以先套用 base backup、再逐筆重放 WAL 到你指定的任意時刻——這就是 PITR(Point-in-Time Recovery,時間點還原)。你能把資料庫還原到「昨天下午 14:30:00」這種精確秒數,代價是設定較複雜。
一句話選型:先用 pg_dump 建立每日備份的基本盤(至少有東西可還原),等資料重要到無法承受幾小時損失時,再導入 WAL-G 的 PITR。
二、升級:雲端一鍵 vs 自架拉 image
「升級」在雲端與自架是兩件本質不同的事,不能混為一談:
| 面向 | 雲端(Supabase Cloud) | 自架(Docker Compose) |
|---|---|---|
| 誰負責 | 平台幫你處理底層 | 你自己全權負責 |
| 怎麼做 | Dashboard 的 Settings/Infrastructure 按指引升級 | 更新 docker-compose.yml 映像標籤 → pull → recreate |
| Postgres major 升級 | 平台提供遷移流程 | 你照官方遷移步驟自己跑 |
| 出錯的後果 | 平台通常有保護與回滾機制 | 你的備份就是唯一的後悔藥 |
自架升級的本質很單純:Supabase 的每個服務都是一個 Docker 映像,升級就是「把映像標籤換成新版本,重新 pull 下來、recreate 容器」。 但「單純」不等於「安全」——升級前沒備份、一次跨好幾個大版本、沒讀 release notes、直接在正式環境動手,任何一項都可能讓你的資料庫回不來。安全升級的順序,下面實作會逐步示範。
三、上線前檢查:六個面向
上線前的生產環境檢查清單,可以歸納成六個面向,每一項都對應一種「沒做就會出事」的風險:
| 面向 | 檢查重點 | 沒做的後果 |
|---|---|---|
| 安全金鑰 | 所有預設密碼/金鑰已換、JWT_SECRET ≥ 64 字元、.env 不進 git | 萬能金鑰公開,資料全裸 |
| RLS 全開 | 所有 public 表已 ENABLE ROW LEVEL SECURITY | 資料對全網公開讀寫 |
| SMTP | 已設自訂 SMTP,不用內建寄信 | 驗證信、重設密碼信發不出去 |
| 資源/連線 | Docker 資源限制、Kong 記憶體上限、連線池、日誌輪替 | OOM Kill、磁碟爆滿、連線耗盡 |
| 備份 | 備份排程已設定且測試過還原 | 出事才發現 dump 檔是壞的 |
| 監控 | uptime、資源、慢查詢、憑證到期告警 | 出事沒人知道,等使用者回報 |
記住:這六項是「AND」不是「OR」——少任何一項,你的自架 Supabase 就有一個致命破口。 下面的實作會把備份與升級的指令攤開,最後給你一份可直接複製的完整檢查清單。
實作範例
這一節把維運三支柱拆成可執行的步驟:① pg_dump 每日備份 → ② pg_restore 還原演練 → ③ WAL-G PITR 概念與設定 → ④ 自架升級步驟 → ⑤ 上線前檢查清單。以下指令假設你的 PostgreSQL 容器名稱是 supabase-db(依你的 compose 專案名而定,用 docker compose ps 確認)。
一、pg_dump 每日邏輯備份
最基本、也最該先做的,是每日 pg_dump。下面是一支可放進 crontab 的備份腳本,它會 dump 資料庫、壓縮、清理過期檔案:
#!/bin/bash
# backup.sh —— 每日 pg_dump 備份腳本
set -euo pipefail
BACKUP_DIR="/opt/backups/postgres"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/supabase_${TIMESTAMP}.dump"
RETENTION_DAYS=7
mkdir -p "${BACKUP_DIR}"
# 從 Docker 容器內執行 pg_dump,-Fc = custom 壓縮格式(可搭配 pg_restore 選擇性還原)
docker exec supabase-db pg_dump \
-U postgres \
-Fc \
--compress=9 \
--no-password \
postgres > "${BACKUP_FILE}"
echo "備份完成:${BACKUP_FILE}($(du -sh "${BACKUP_FILE}" | cut -f1))"
# 選用:上傳到 S3 / R2 異地保存(備份和資料庫不要放在同一台機器!)
# aws s3 cp "${BACKUP_FILE}" "s3://your-bucket/postgres-backups/"
# 清理超過保留天數的舊備份
find "${BACKUP_DIR}" -name "*.dump" -mtime +${RETENTION_DAYS} -delete
echo "已清理超過 ${RETENTION_DAYS} 天的備份"
這裡有幾個關鍵設計要理解:
-Fc(custom format) 是壓縮的二進位格式,比純 SQL 小很多,而且還原時可以用pg_restore只挑特定資料表還原,彈性最高。- 異地保存不能省:備份檔如果和資料庫躺在同一台伺服器,那台機器一掛(硬碟壞、被駭、機房失火),備份跟著陪葬。務必把備份上傳到另一個地方——S3、Cloudflare R2、甚至另一台機器都好。這是 3-2-1 備份原則的精神(至少 3 份、2 種媒介、1 份異地)。
把腳本加進 crontab,讓它每天凌晨自動跑:
# 編輯 crontab:crontab -e
# 每天凌晨 2 點執行備份,輸出寫進 log
0 2 * * * /opt/scripts/backup.sh >> /var/log/supabase-backup.log 2>&1
二、pg_restore 還原演練(這一步才是重點)
備份腳本寫好、cron 也跑了,不代表你有備份——你只有「一堆還沒驗證過的檔案」。 唯一能證明備份有效的方法,是真的還原一次。下面示範怎麼把某個 dump 檔還原回去:
# 1. 先停掉會寫入資料庫的服務(保留 db 容器運行)
docker compose stop rest auth realtime storage
# 2. 用 pg_restore 還原(--clean --if-exists 會先清掉現有物件再還原)
docker exec -i supabase-db pg_restore \
-U postgres \
-d postgres \
--clean \
--if-exists \
< /opt/backups/postgres/supabase_20261102_020000.dump
# 3. 還原完成後,重啟剛剛停掉的服務
docker compose start rest auth realtime storage
但真正的還原演練,不該在正式資料庫上做——那太危險了。正確的演練是把 dump 檔還原到一個隔離的測試環境(另一台機器、或本機另起一套乾淨的 Supabase),然後驗證:資料筆數對不對?關鍵資料表能不能查?使用者登得進去嗎?建議的演練節奏是:
- 每月一次:把最新備份還原到隔離環境,驗證資料完整性
- 每季一次:模擬完整災難復原,計時量測 RTO(Recovery Time Objective,復原時間目標)——「從發現故障到服務恢復,總共要多久?」
- 每次重大遷移或升級後:立即做一次備份驗證
把這個習慣養成,你才敢在半夜資料庫崩掉時,對自己說「別慌,我還原過,我知道怎麼救」。
三、WAL-G PITR:任意秒數還原
當 pg_dump 的「只能回到上次備份」不夠用時,就輪到 WAL-G 上場。它的原理前面講過:定期做 base backup + 持續歸檔 WAL,還原時重放 WAL 到任意時刻。設定分幾步。
首先,擴充 Supabase 的 PostgreSQL 映像,把 WAL-G 二進位裝進去:
# Dockerfile.postgres-walg
FROM supabase/postgres:15.1.1.88
ARG WALG_VERSION=3.0.3
RUN curl -fsSL \
"https://github.com/wal-g/wal-g/releases/download/v${WALG_VERSION}/wal-g-pg-ubuntu-20.04-amd64.tar.gz" \
| tar xz -C /usr/local/bin/ \
&& chmod +x /usr/local/bin/wal-g
接著,在 PostgreSQL 設定裡開啟 WAL 歸檔(postgresql.conf):
wal_level = replica
archive_mode = on
archive_timeout = 60 # 每 60 秒強制歸檔一次,低流量時最多丟 1 分鐘資料
archive_command = 'source /etc/wal-g/env.conf && wal-g wal-push %p'
restore_command = 'source /etc/wal-g/env.conf && wal-g wal-fetch %f %p'
WAL-G 的 S3 環境設定(/etc/wal-g/env.conf),支援 Cloudflare R2 這類 S3 相容儲存:
export WALG_S3_PREFIX=s3://your-backup-bucket/wal-g/
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
export AWS_REGION=ap-northeast-1
# 使用 Cloudflare R2 時額外指定 endpoint:
# export AWS_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
設定好之後,先推一個 base backup,再排程每日備份:
# 在 db 容器內建立第一個 base backup
docker exec supabase-db bash -c \
'source /etc/wal-g/env.conf && wal-g backup-push /var/lib/postgresql/data'
# 在 db 容器的 crontab:每天凌晨 3 點做 base backup、只保留最近 7 份
0 3 * * * source /etc/wal-g/env.conf && wal-g backup-push /var/lib/postgresql/data
0 4 * * * source /etc/wal-g/env.conf && wal-g delete retain FULL 7 --confirm
真正需要 PITR 時,還原流程的核心是「取回 base backup + 設定還原目標時間 + 讓 PostgreSQL 自動重放 WAL」:
# 1. 停掉 db 容器
docker compose stop db
# 2. 備份現有資料目錄(以防還原出錯還能退回)
mv /var/lib/docker/volumes/supabase_db/_data \
/var/lib/docker/volumes/supabase_db/_data.bak
# 3. 取回最新 base backup
source /etc/wal-g/env.conf
wal-g backup-fetch /var/lib/postgresql/data LATEST
# 4. 設定還原目標時間,並建立 recovery.signal 觸發還原模式
echo "recovery_target_time = '2026-11-02 14:30:00 UTC'" \
>> /var/lib/postgresql/data/postgresql.conf
echo "recovery_target_action = 'promote'" \
>> /var/lib/postgresql/data/postgresql.conf
touch /var/lib/postgresql/data/recovery.signal
# 5. 啟動 db,PostgreSQL 會自動重放 WAL 到目標時間
docker compose start db
# 6. 盯著日誌看還原進度
docker compose logs -f db | grep -E "(recovery|restored|PITR)"
WAL-G 設定較複雜,實際路徑與版本請以官方文件為準;但概念記住就好:base backup 是起點、WAL 是逐筆變更、PITR 就是「從起點重放到你要的那一秒」。
別忘了 Storage(物件儲存)也要備份。資料庫備好了,但使用者上傳的檔案(存在 MinIO / Storage volume)也是資料。可以定期
tar打包 storage volume,或用mc mirror把 bucket 同步到異地 S3。
四、自架升級:拉新 image、recreate 容器
自架升級的本質是換映像。安全升級的關鍵不是指令,而是順序。先看指令:
# 方法一:官方若提供更新腳本,直接跑(依你的版本而定)
# sh update.sh
# 方法二:手動升級——修改 docker-compose.yml 裡的映像標籤到新版本後:
docker compose pull # 拉取新版映像
docker compose up -d # 用新映像重建有變動的容器
# 只升級單一服務(例如只更新 studio)
docker compose pull studio
docker compose up -d studio
但在敲這些指令之前,請務必照這個順序把安全網架好:
- 先完整備份。升級前一定先跑一次
pg_dump(或 WAL-G base backup)。升級是少數「可能弄壞資料」的操作,這份備份就是你唯一的後悔藥。 - 讀 release notes。到官方 repo 看新版本的 release notes,確認有沒有 breaking change、需不需要手動執行 migration。
- 先在 staging 演練。自架沒有「多環境」的托管支援,所以正式升級前,務必在一套獨立的暫存環境跑過同樣的升級流程,確認沒問題再上正式。
- 不要一次跨多個大版本。尤其 PostgreSQL 的 major version 升級牽涉底層資料格式,必須照官方遷移流程逐版升,絕不能從 14 直接跳到 17。
- 升級後驗收。用
docker compose ps確認每個容器都healthy,再跑一輪煙霧測試(smoke test):登入 Studio、讀寫一筆資料、跑一次認證登入。全綠了才把流量切回來。
至於雲端升級就單純多了:在 Supabase Dashboard 的 Settings / Infrastructure 區塊,依官方指引升級 Postgres 版本或平台版本,底層由平台處理(具體選項與流程以官方 Dashboard 當下顯示為準)。雲端與自架最大的差別就在這裡——雲端把升級的風險與複雜度托管掉了,自架則全部回到你手上。
五、上線前生產環境檢查清單
最後,把前面所有零件收斂成一份可以逐項打勾的驗收單。上正式環境前,對照這份清單一項一項確認:
【安全金鑰】
□ 所有預設密碼/金鑰已更換(POSTGRES_PASSWORD、JWT_SECRET、DASHBOARD_PASSWORD)
□ ANON_KEY / SERVICE_ROLE_KEY 用你的 JWT_SECRET 重新簽出(不可沿用預設)
□ JWT_SECRET 至少 64 字元
□ .env 已在 .gitignore,未提交進版本控制(生產建議用外部 secret 管理器)
□ service_role key 未出現在任何前端程式碼或公開 repo
【RLS 全開】
□ 所有 public schema 的資料表都已 ENABLE ROW LEVEL SECURITY
□ 每張開了 RLS 的表都有明確的存取策略(RLS 開了卻沒策略 = 全部拒絕)
□ RLS 策略比對的欄位(如 user_id)已建立索引
【SMTP 與 Auth】
□ 已設定自訂 SMTP(不用內建寄信的嚴格速率限制)
□ JWT_EXPIRY 設為 3600(1 小時),搭配 Refresh Token 輪替
□ OTP 有效期設為 ≤ 3600 秒
【資源與連線】
□ Docker 資源限制已設(防止某個容器 OOM Kill 拖垮整台)
□ Kong 已設 KONG_MEM_CACHE_SIZE(防記憶體從 200MB 暴衝到 2.5GB+)
□ 所有服務設 restart: unless-stopped(重開機自動恢復)
□ 日誌輪替已設(max-size / max-file,防磁碟被日誌塞滿)
□ Supavisor 連線池已正確設定,避免雙重池化
【對外安全】
□ 反向代理已啟用,Kong 的 8000 未直接對外
□ HTTPS/TLS 已設定(TLS 1.2+,憑證自動續期)
□ 防火牆只開 80 / 443 / SSH,5432 與 8000 不對外
【備份】
□ 備份排程已設定(pg_dump 或 WAL-G)
□ ★ 已實際測試過還原(這一項最常被跳過,也最致命)
□ 備份異地保存(不和資料庫放同一台機器)
□ Storage(物件儲存)也已納入備份
【監控】
□ 外部 uptime 監控(UptimeRobot / Better Uptime 等)
□ 磁碟、記憶體、CPU 使用率告警(磁碟警戒線建議 80%)
□ 慢查詢告警(> 1 秒)
□ SSL 憑證到期告警
□ 容器 healthcheck 已為所有服務設定
災難復原(DR)不是一份清單,而是一套「當最壞情況發生時,你知道怎麼辦」的預案。 把上面的檢查做完後,再問自己三個問題:(1) 如果整台伺服器現在消失,我能在多久內從備份重建?(這是你的 RTO);(2) 我最多會損失多少資料?(這是你的 RPO,Recovery Point Objective——pg_dump 每日備份的 RPO 是 24 小時,WAL-G PITR 可壓到幾秒);(3) 復原步驟有沒有寫成文件,還是只在我腦子裡?能清楚回答這三題,你的自架 Supabase 才算真正做好了維運準備。
常見錯誤與最佳實踐
坑一:寫了備份腳本,卻從沒測過還原。 這是維運最致命的自我欺騙。cron 每天跑、log 顯示「備份完成」,你以為高枕無憂——直到真的要還原,才發現 dump 檔是壞的、或還原指令根本跑不通、或漏備了某個關鍵 schema。正確做法:把「還原演練」排進行事曆,每月至少一次把最新備份還原到隔離環境驗證,並計時量測 RTO。記住那句話——沒有測試過還原的備份,等同於沒有備份。
坑二:直接在正式環境升級,還一次跨好幾個大版本。
「反正就 docker compose pull 一下」的心態,是資料庫災難的開端。沒先備份、沒讀 release notes、沒在 staging 演練,升級後容器起不來或資料格式不相容,你連退路都沒有。尤其 PostgreSQL 的 major 版本升級牽涉資料格式,絕不能跳版。正確做法:升級前先完整備份 → 讀 release notes → 在 staging 跑一次 → 逐版升(不跨 major)→ 升級後跑煙霧測試確認再切流量。
坑三:上線了才發現金鑰還是預設值。
沿用 .env.example 的 JWT_SECRET 與 service_role key 上線,等於把繞過所有 RLS 的萬能鑰匙公開在 GitHub 上,任何人知道你網址就能讀寫你全部資料。正確做法:把「金鑰已全換」放進上線檢查清單的第一項,用 generate-keys.sh 換掉所有預設值,ANON_KEY / SERVICE_ROLE_KEY 必須用你的新 JWT_SECRET 重新簽出。
坑四:備份和資料庫放在同一台機器。 備份的意義是「當這台機器出事時能救回來」,結果備份就躺在同一顆硬碟上——硬碟壞了、機房失火、被勒索軟體加密,備份跟著一起沒。正確做法:遵循 3-2-1 原則,至少把一份備份異地保存到 S3 / R2 / 另一台機器,而且異地那份也要偶爾驗證還原。
坑五:沒有監控,出事靠使用者回報。 磁碟悄悄滿了、某個容器半夜被 OOM Kill、連線數爆到上限——這些在自架環境天天可能發生,若沒有告警,你會在使用者哀嚎「網站掛了」時才知道,而那通常已經是數小時之後。正確做法:上線前就把 uptime 監控、資源告警(磁碟 80%、記憶體、CPU)、慢查詢告警、憑證到期告警全部接好,讓系統在出事前主動通知你。
最佳實踐總結:
- 備份的價值在於還原:排程只是一半,真正測試過還原才算數;RTO/RPO 要心裡有數
- 異地保存:遵循 3-2-1,別讓備份和資料庫同生共死
- 升級要有安全網:先備份 → 讀 release notes → staging 演練 → 逐版升 → 煙霧測試
- 不跨 major 版本:PostgreSQL major 升級照官方遷移流程逐版走
- 上線清單逐項打勾:金鑰、RLS 全開、SMTP、資源/連線、備份、監控,六項缺一不可
- 監控要在出事前接好:讓系統主動告警,而不是等使用者回報
- 細節以官方為準:映像版本、升級步驟、雲端備份層級都可能隨版本調整
小結
這是 Supabase 系列教學的第 044 篇,也是自架段(SB-5)的第二篇。上一篇《自架部署(Docker Compose)》教你把整套 Supabase 用 Docker Compose 架起來、登入 Studio;這一篇補上了自架最硬的維運面——架起來只是第一天,養得好才是接下來的每一天。
核心觀念濃縮成一句話:自架版沒有雲端幫你托管的自動備份與 PITR,備份、升級、上線檢查全部得自己扛;用 pg_dump 建立每日備份的基本盤、必要時用 WAL-G 做 PITR 任意秒數還原,而且一定要真的測試過還原;升級前先備份、讀 release notes、在 staging 演練、逐版升不跨 major;最後對照一份涵蓋金鑰、RLS、SMTP、資源、備份、監控的上線檢查清單逐項打勾,才敢把流量切上去。
- 備份策略:
pg_dump邏輯備份(粒度到上次備份)vs WAL-G 物理備份 + PITR(任意秒數),先求有再求精 - 還原演練:沒測過還原的備份等同沒有;每月演練、量測 RTO/RPO
- 升級流程:自架 = 拉新 image + recreate,關鍵在順序(備份→release notes→staging→逐版→煙霧測試);雲端則走 Dashboard,以官方為準
- 上線檢查:金鑰、RLS 全開、SMTP、資源/連線、備份、監控——六個面向一項都不能漏,並想清楚災難復原的 RTO/RPO
自架 Supabase 到這裡,你已經能「架起來」也能「養得好」了。但維運不是只有備份與升級——你還需要一雙能持續盯著系統的眼睛,以及在資料庫裡跑排程、處理非同步任務的能力。下一篇《監控與 pg_cron/pgmq》,我們會補上這最後一塊:怎麼用 pg_cron 在資料庫內排程定時任務、用 pgmq 把 PostgreSQL 當成訊息佇列處理背景工作,以及怎麼搭起一套讓你安心睡覺的監控與告警。把「架起來、養得好、看得住」三塊接起來,才是一套真正扛得住生產流量的自架 Supabase。