解剖 Supabase:从 Postgres 内核到实时订阅,开源 BaaS 的完整拼图
【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabase
当 2026 年的技术圈还在争论"vibe coding 到底可不可靠"时,一个负责给这些 AI 生成的代码"兜底"的后端平台已经悄然站上了百亿美元估值——这就是 Supabase。它没有自研一套全新的数据库,而是选择把 30 岁的 Postgres 重新包装,再配上实时订阅、身份认证、对象存储和边缘函数,拼出了一张完整的开源 BaaS 版图。这张拼图究竟是怎么咬合在一起的?本文直接深入仓库源码,从 Docker 编排、数据库初始化脚本到官方示例,逐层拆解。
一张 Docker Compose 清单,看懂整个架构
拆解 Supabase 最直接的方式,是看它的自托管编排文件 docker/docker-compose.yml。这份文件定义了整整 11 个核心服务,每个服务对应一个可独立替换的开源组件:
| 服务 | 镜像/组件 | 职责 |
|---|---|---|
db | supabase/postgres:17.6.1.136 | 数据库内核,预装扩展 |
rest | postgrest/postgrest:v14.17 | 把表变成 RESTful API |
auth | supabase/gotrue:v2.196.0 | JWT 认证与会话管理 |
realtime | supabase/realtime:v2.134.10 | WebSocket 实时订阅 |
storage | supabase/storage-api:v1.74.0 | S3 风格对象存储 |
functions | supabase/edge-runtime:v1.76.2 | Deno 边缘函数 |
meta | supabase/postgres-meta:v0.99.0 | 数据库管理 API |
api-gw | envoyproxy/envoy:v1.39.1 | 统一 API 网关 |
supavisor | supabase/supavisor:2.9.12 | Postgres 连接池 |
imgproxy | darthsim/imgproxy:v3.31.4 | 图片实时处理 |
studio | supabase/studio | 可视化控制台 |
注意一个细节:网关服务在 README 中的描述是 Envoy,而历史版本用的是 Kong。docker-compose.yml里保留了envoy与kong两个网络别名,意味着内部配置无论引用哪个主机名都能解析到当前激活的网关——这种"平滑换引擎"的设计,正是模块化架构的最大红利:任何一层组件都可以被替换,而不必重写其余部分。
Auth、Storage、Realtime、Edge Functions:四大模块如何各司其职
Auth:以 Postgres 为用户的 GoTrue
认证服务supabase/gotrue直接把自己的状态写进 Postgres。在 docker/docker-compose.yml 中可以看到它的数据库连接串指向supabase_auth_admin这个专用角色,并且通过大量环境变量暴露能力开关:邮箱/手机号注册(GOTRUE_EXTERNAL_EMAIL_ENABLED、GOTRUE_EXTERNAL_PHONE_ENABLED)、匿名用户(GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED)、TOTP 与手机 MFA、SAML SSO,甚至支持通过pg-functions://URI 把认证钩子直接挂到数据库函数上——认证逻辑和业务数据从此共享同一套存储与事务语义。
Realtime:轮询复制槽,广播 JSON
Realtime 是整张拼图里最有辨识度的一块。它在 docker/volumes/db/realtime.sql 中只做了一件事:创建_realtimeschema 并授权给supabase_admin。这个 Elixir 服务的工作方式与常见的"数据库变更事件推送"完全不同——它轮询 Postgres 内置的复制功能(WAL 复制槽),把 insert/update/delete 转成 JSON,再通过 WebSocket 广播给通过 JWT 授权的客户端。也就是说,实时能力不是 API 层模拟出来的,而是直接建立在数据库复制机制之上,天然与 RLS 权限模型打通。
Storage:文件放 S3,权限留在 Postgres
存储模块的哲学是"文件与元数据分离":docker/docker-compose.yml 中storage服务的STORAGE_BACKEND默认为本地文件系统,但可以一键切换到 S3 后端(GLOBAL_S3_ENDPOINT等配置),同时权限判断交给 PostgREST(POSTGREST_URL: http://rest:3000),JWT 校验则复用AUTH_JWT_SECRET。这意味着对象存储的授权策略和数据库的 RLS 策略同源,不存在"一套 API、两套权限"的心智负担。仓库里的 examples/storage/protomaps 示例展示了完整的组合拳:把离线地图的 PMTiles 文件上传到私有 bucket,再用 Edge Functions 代理做细粒度访问控制,前端通过pmtiles://<project_ref>.supabase.co/functions/v1/maps-private/my_area.pmtiles直接渲染矢量地图。
Edge Functions:带 JWT 校验的 Deno Worker
Edge Functions 运行在supabase/edge-runtime上,它不是一个黑盒 FaaS。docker/volumes/functions/main/index.ts 展示了入口服务的真实面貌:main服务本身就是一个标准 Deno 模块,负责用jose解析 JWKS、校验 JWT,并为子函数定义了一整套错误码(UNAUTHORIZED_LEGACY_JWT、UNAUTHORIZED_ASYMMETRIC_JWT、WORKER_RESOURCE_LIMIT等)。而 docker/volumes/functions/hello/index.ts 则演示了开发者写函数的方式——withSupabase封装自动处理publishable/secret两种密钥模式,ctx.supabaseAdmin绕过 RLS 用于特权操作。整个函数就是一个fetch处理器,部署形态与 Docker 服务完全同构,没有引入第二套运行时心智。
Postgres 内核如何被"包装"成对开发者友好的 BaaS
自动化 API:表即接口
BaaS 体验的核心秘密,是 PostgREST——一个把 Postgres 数据库直接变成 RESTful API 的 web 服务器。在rest服务的配置里,PGRST_DB_SCHEMAS决定哪些 schema 暴露为 API,PGRST_DB_MAX_ROWS默认限制单次返回 1000 行以防止恶意大请求,而PGRST_DB_ANON_ROLE: anon定义了匿名访问角色。开发者只需要建表,REST 端点就自动存在,还能通过pg_graphql扩展获得 GraphQL 接口——仓库 README 的 架构图 清晰展示了这张分层关系。
行级安全(RLS):唯一正确的权限模型
前端直连数据库,权限怎么办?答案在 examples/todo-list/nextjs-todo-list/supabase/migrations/20230712094349_init.sql 这份官方示例迁移文件里:
alter table todos enable row level security; create policy "Individuals can create todos." on todos for insert with check (auth.uid() = user_id); create policy "Individuals can view their own todos. " on todos for select using (auth.uid() = user_id); create policy "Individuals can update their own todos." on todos for update using (auth.uid() = user_id); create policy "Individuals can delete their own todos." on todos for delete using (auth.uid() = user_id);这套模式是 Supabase 安全模型的基石:客户端拿到anon key只能"匿名访问"数据库,用户登录后 token 切换为带auth.uid()声明的 JWT,RLS 策略自动生效——数据隔离不是靠 API 层代码,而是数据库内核强制执行。docker/volumes/db/roles.sql进一步揭示了角色分工:authenticator(PostgREST 连接)、supabase_auth_admin(GoTrue)、supabase_storage_admin(存储)、supabase_functions_admin(函数)各司其职,权限最小化到进程级别。
数据库函数与 AI 能力:内核即功能
Supabase 还不断把 AI 能力下沉到数据库内核。supabase/migrations/20250714120000_hybrid_search.sql 展示了一个典型的混合检索实现:用 RRF(倒数排名融合)把全文搜索(websearch_to_tsquery)与向量搜索(query_embedding vector(1536))的结果融合排序,一条 SQL 函数即可同时支撑关键词检索和语义检索。这解释了为什么社区普遍认为"2026 年的 Supabase 对 AI 应用至关重要"——向量、全文、实时订阅、边缘函数在同一个数据底座上原生协作,而不是几个割裂的云服务。
与自建整套开源组件的成本对比
把所有组件拆开看,它们几乎都是可以单独部署的开源软件:Postgres、PostgREST、GoTrue、Realtime、Storage API、Envoy、Supavisor。那么"自建"与"用 Supabase"的本质区别是什么?
自建的成本清单:你需要至少 7 个长期运行的服务进程,每个都要处理配置、升级、监控、安全补丁和相互间的版本兼容;需要为authenticator、anon、service_role等角色设计密钥轮换;需要自己调通 Envoy 路由、JWT 签名校验、连接池参数;还要在 WAL 复制槽、Realtime 轮询、imgproxy 缓存之间做容量规划。这些运维债不会消失,只会转移到你的团队身上。
Supabase 的解法:托管平台把这份复杂度封装为"一个项目 + 两个 key",本地开发则通过supabase/config.toml一键复刻生产环境——仓库里这份配置文件用 100 余行声明式配置覆盖了 API 端口、暴露的 schema、最大行数、存储限制、认证开关与 OAuth 提供商,配合 CLI 的db push让迁移在本地与远端之间无缝流转。换句话说,开源组件解决的是"能不能跑",Supabase 解决的是"不用想怎么跑"。
成本对比的结论因此很清晰:如果团队规模足够大、且愿意为数据库基础设施投入专职运维,自建堆栈完全可行;但对于大多数 SaaS、移动应用与 AI 应用团队,把运维复杂度集中到平台、用 SQL 和 RLS 策略换取开发速度,才是"用周末开发百万并发应用"的现实路径。这也是 Supabase 从 2024 年融资 1.5 亿美元、到收购 Turso 布局"AI 智能体的数百万个独立数据库"、再到如今百亿美元估值的底层逻辑——它不是另一个数据库,而是把数据库行业的全部积累,翻译成了前端开发者最熟悉的语言。
结语:一张拼图,两种打开方式
回看这张拼图:Postgres 是内核,PostgREST 是翻译官,GoTrue 是门禁,Realtime 是脉搏,Storage 是仓库,Edge Runtime 是触角,Envoy 与 Supavisor 是枢纽——每一块都是开源的、可替换的、可自托管的。这既是 Supabase 最大的工程成就,也是它最深的护城河:当别人在比拼封闭平台的接口数量时,它把整个系统的图纸公开在了仓库里,任何人都能研究它、部署它,甚至替换掉其中任何一块拼图。
【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考