一、为什么我选择 Supabase 而不是自建后端

过去一年, 我在 1 人 PM 团队跑一个数据治理项目, 后端层比较了 3 个方案: Firebase (NoSQL) / 自建 Express + Postgres / Supabase. Firebase 把数据库藏在 NoSQL 黑盒里, 查业务字段要建复合索引还慢; 自建 Postgres 要自己搭连接池 / 迁移工具 / 备份脚本. 一个 7 月开始的项目, 我选了 Supabase:

  • BaaS 三件套: Postgres 17 + Auth + Realtime + Storage + Edge Functions, 一站搞定

  • SQL 是事实标准, 不是 NoSQL 黑盒

  • 一个月内置了 5 张业务表 + 18 个 cron 任务, 0 自建后端代码

本文后面 7 节都用真实踩坑说话, 不是什么架构图, 是一行一行跑出来的结论。


二、第一坑: 项目暂停 (“7 天不活动” 警告)

开项目时, 一篇社区帖让我担心: “Supabase 免费项目 7 天不活动会被自动暂停”. 我立刻查了官方文档, 搜 0 命中 “7 days auto-pause”, 真实条款是:

  • Free plan 限 2 个项目

  • 暂停是手动操作 (用户点 Pause), 不是自动

  • 真实规则里没有 “自动暂停” 4 个字

但社区帖可能出自邮件通知或监控保守起见. 预防方案: 接自动 cron 让库每天都有写. 0 token 消耗 5 credits/天的 cron 最佳:

0 6 * * *   Supabase boss_documents 自动同步   (每天 6:00)
5 6 * * *   Supabase cron_state 自动同步      (每天 6:05)

这两个 cron 是 no_agent 模式, LLM 不参与, 0 token 写入, 7 月初实测 15/15 ok 进 Supabase cron_state 表.


三、第二坑: Pooler vs Direct Connection

沙箱数据中心 IP 是新加坡机房 50.7.252.26. 裸连 db.<ref>.supabase.co:5432 走 Cloudflare 必 403 1010 风控. 我是怎么发现的:

$ psql "postgresql://postgres.<your-ref>:<your-password>@db.<your-ref>.supabase.co:5432/postgres"
psql: error: connection to server ...:5432 ...: Cloudflare 风控

正解 — Pooler 转接:

<region-prefix>.pooler.supabase.com:6543 (IPv4 通)

注意 hostname 是 aws-1-, 不是 ****aws-0-! 我第一版写错, 报 “tenant/user postgres.<your-ref> not found”, 折腾 30 分钟.

附带 2 个生产经验:

  • 密码永远不放 shell 命令行 — 沙箱会自动脱敏成 ***, 命令认证直接失败. 正解: PGPASSWORD 环境变量 + Python subprocess

  • SQLAlchemy 比裸 psycopg2 更好用 — ORM + 事务 + 连接池, 业务代码可读


四、第三坑: RLS 5 大误解 (实战)

我开的 5 张表全部启用 RLS, 5 周内零越权查询. 实战踩过的 5 个误解:

# 误解 实情
1 “RLS 一定要建 user 表” 公开表的策略可以是 USING (true)
2 “service_role 必须用” 我们用 sb_secret 41 字符新格式 key 替代 JWT
3 “RLS 写策略一定要 user_id=auth.uid()” 我们用 service_role 写, 策略 USING (true) 即可
4 “远程 MCP 一定要 OAuth” 国内网络 stdio 本地 npx 包装反而稳
5 “MCP 一定要 mutation 权限” hermes 自动加 --read-only 是好事, 写库走 SQLAlchemy

最实用的一段策略 SQL (示范):

ALTER TABLE boss_documents ENABLE ROW LEVEL SECURITY;
CREATE POLICY public_read ON boss_documents FOR SELECT USING (true);
CREATE POLICY service_write ON boss_documents FOR INSERT
  WITH CHECK (current_setting('app.role', true) = 'service_role');

关键: 业务表用 service_role 写但仍然全表 USING (true), 因为这些是"主理人"私有元数据, 而非用户数据.


五、第四坑: 凭据管理 (API Key 永远不准出现在代码里)

我见过太多泄漏事故, 规则钉死:

  • shell 命令行写 token → 沙箱脱敏 + 历史走 Git

  • 截图贴推文 → 被爬

  • README 写 “请看 .env.example” → .env.example 也是代码

  • 用 pydantic-settings v2.14.2 统一从 .env 加载, 单点配置

# hermes_settings.py - 统一加载器 (节选, 已脱敏)
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    supabase_access_token: str = ""       # 从 .env 加载
    supabase_project_ref: str = ""        # 从 .env 加载
    supabase_db_password: str = ""        # 从 .env 加载
    supabase_secret_key: str = ""         # sb_secret 41 字符, 从 .env 加载

    model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")

settings = Settings()

绝对不要 把任何上文出现的 44 字符 / 41 字符 / 36 字符字面量粘进博客. 读者追问时, 让他们去 Supabase Dashboard 自己生成.


六、第五坑: MCP server read-only 模式 + 双轨写库

我配置 Supabase MCP 时踩了一个 6/29 的真坑:

# config.yaml (示范, 已脱敏)
supabase:
  command: /root/.hermes/node/bin/npx
  args:
  - -y
  - '@supabase/mcp-server-supabase@latest'  # hermes 自动加 @latest
  - --project-ref=<your-project-ref>        # 你的项目 ref
  - --read-only                             # hermes 自动加 read-only
  env:
    SUPABASE_ACCESS_TOKEN: "<your-token-here>"
    SUPABASE_DB_PASSWORD: "<your-password-here>"

3 个意外的坑:

  1. --read-only 是 hermes 自动加的, 我没写, 它会自作主张加

  2. @latest 也自动加, pinned version 失效

  3. MCP 修改 config 后必须 hermes gateway restart 才生效 — 别问我是怎么试过的

好处: mutation 工具 (apply_migration / create_branch / deploy_edge_function) 全被锁. 写库走 SQLAlchemy 直连, 不受 read-only 限制.


七、第六坑: 18 个 cron 任务 = 不只是 Supabase, 是数据生命周期

很多人以为 “Supabase = 数据库”, 错. Supabase 真正的价值是和 CI/cron 配合. 我跑通 4 层数据架构:

  • L0 source: Supabase hermes_mistakes (人工认错)

  • L1 hot: PG memory_entries (每小時同步, 192.168.11.1:5432)

  • L2 warm: Upstash Redis data_lake:* (90 天 TTL)

  • L3a cold: PG data_lake_archived (周末清理落库)

  • L3b cold: Supabase data_lake_synced (metadata + pg_archive_id)

18 个 cron 中, 16 个是业务 (求职日报 / 早安图 / 监控), 2 个就是 Supabase 自动同步:

  • 每天 6:00 推 boss_documents 进 Supabase

  • 每天 6:05 推 cron_state 进 Supabase (16 行, 含自己)

周末 20:00 还跑 weekly cleanup, 把 Redis dump 落到 PG + Supabase metadata.


八、踩坑对照总表

踩坑分类 现象 根因 正解
项目暂停 听说 7 天不活动自动暂停 官方文档无明文条款 接 cron 0 6 * * * 防一手
Pooler 连接 direct 5432 403 1010 沙箱机房 IP 被 Cloudflare 风控 aws-1-ap-northeast-2.pooler.supabase.com:6543
RLS 策略误解 “必须 user_id=auth.uid()” 文档例子只讲用户表 公开表 USING (true) + service_role 写
密码脱敏 PGPASSWORD=*** psql 认证失败 沙箱 shell 脱敏 环境变量 + Python subprocess
MCP read-only mutation 工具被禁 hermes 自动加 --read-only 写库走 SQLAlchemy 直连
cron timezone DateTime 字段写毫秒 格式错, 自动日期失败 写 “YYYY-MM-DD HH:mm:ss” 字符串
postgrest 冲突 UPSERT 409 conflict 默认 resolution 错 header Prefer: resolution=merge-duplicates
凭据泄漏 截图 / 代码 commit / 推文 习惯性粘贴 用 pydantic-settings 单点加载, 永远不写死

九、实战效果数据 (7/1 实测)

项目 数量 用时 成本
Supabase 建表 5 张 (cron_state/boss_documents/boss_profile/boss_preferences/hermes_mistakes) 30 分钟 0 USD (FREE plan)
boss_preferences 26 → 35 条精选 35 条 1 周 0 USD
cron 自动同步 18 个 (含 2 个 Supabase 自动) 0 token 0 USD
业务失误表 12 条 → 5 类 mistakes 95% 命中率 0 USD
数据持久化 3 重 (.env × 2 + Postgres + b64) 永远 0 USD
7 张源文档自动镜像 91 条 boss_documents 30 秒/次 0 USD

十、写给读者的 3 句话

  1. Supabase 是个数据库, 但跑得顺的前提是有 cron — 没 cron 你的项目迟早进入"静默期"

  2. MCP read-only 是 boss, 不是 lock — 写库 SQLAlchemy 照写

  3. API key 永远从 pydantic-settings 走 — 哪怕一段 shell one-liner, 也用 env 加载


参考资料

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐