Database

数据库提供商

将 Nebutra 连接到 Neon、Supabase 或 PlanetScale Postgres — 每个提供商的环境变量、连接池和迁移设置。

Nebutra 开箱即用支持三个托管 PostgreSQL 提供商:Neon、Supabase 和 PlanetScale Postgres。应用程序代码在这些提供商之间保持一致;差异主要是连接字符串、连接池行为,以及如何启用提供商托管的 PostgreSQL 扩展。

此页面列出的受支持提供商都是 PostgreSQL。Prisma 中继续保留 provider = "postgresql",提交生成的迁移文件,并通过 DIRECT_URL 运行迁移。

PlanetScale Vitess/MySQL 与 PlanetScale Postgres 不是同一条支持路径。它需要单独的 schema、adapter、relation、index 和 migration 策略,因此目前只作为 future/template path,而不是受支持的核心 runtime。

Neon 是默认提供商。它是一个无服务器 PostgreSQL 平台,具有分支、自动暂停和慷慨的免费套餐。内置 PgBouncer 连接池。

为什么选择 Neon

  • 分支 — 为每个功能分支或 PR 创建隔离的数据库分支,零数据复制成本
  • 无服务器 — 空闲时自动缩减到零;休眠数据库不收取计算费用
  • 自动暂停 — 免费套餐数据库在 5 分钟不活动后暂停,约 500 毫秒内恢复
  • pgvector — 在所有 Neon 数据库上默认启用

连接字符串格式

Neon 为每个数据库提供两个 URL:用于运行时查询的连接池 URL(通过 PgBouncer),以及用于迁移的直接 URL。

# 连接池 — 用于所有应用程序查询
postgresql://USER:[email protected]/neondb?sslmode=require&pgbouncer=true

# 直接连接 — 仅用于迁移
postgresql://USER:[email protected]/neondb?sslmode=require

环境变量

# 运行时查询(通过 PgBouncer 连接池)
DATABASE_URL="postgresql://USER:[email protected]/neondb?sslmode=require&pgbouncer=true"

# 仅迁移(直接连接 — 绕过连接池)
DIRECT_URL="postgresql://USER:[email protected]/neondb?sslmode=require"

Prisma 数据源与迁移配置

datasource db {
  provider = "postgresql"
}
const runtimeDatabaseUrl = process.env.DATABASE_URL ?? "";
const migrationDatabaseUrl = process.env.DIRECT_URL ?? process.env.DATABASE_URL;

通过 PgBouncer 的连接池

Neon 的 PgBouncer 以事务模式运行 — 连接仅在单个事务期间保持,然后归还到连接池。这使得少量实际 PostgreSQL 连接可以支持数千个并发应用程序连接。

PgBouncer 事务模式不支持跨事务持久的 SET 语句(例如用于 RLS 的 SET LOCAL)。Nebutra 的 withRls 在事务内部设置租户变量,这与事务模式连接池兼容。

开发用数据库分支

从 Neon 控制台或 CLI 创建分支,为功能分支获取架构的隔离副本:

# Neon CLI
neon branches create --name feature/new-model --parent main

每个分支都有自己的 DATABASE_URL。在本地 .env 或 Vercel 的每分支环境变量设置中设置它。

Supabase 是一个 PostgreSQL 平台,提供托管控制台、内置认证、存储和实时订阅。连接池由 Supavisor 提供。

为什么选择 Supabase

  • 托管控制台 — 在 Supabase Studio UI 中浏览表、运行 SQL 和查看 RLS 策略
  • Supavisor — 支持 RLS 所需 SET LOCAL 语句的会话模式连接池
  • pgvector — 作为一流扩展提供,可从控制台启用
  • 存储 — 与数据库同置的 S3 兼容对象存储(由 @nebutra/uploads 使用)

启用 pgvector

在运行迁移之前,从 Supabase 控制台启用 pgvector 扩展:

控制台 → 数据库 → 扩展 → 搜索 "vector" → 启用

或通过 Supabase SQL 编辑器:

CREATE EXTENSION IF NOT EXISTS vector;

连接字符串格式

Supabase 为每个项目提供连接池 URL(Supavisor)和直接 URL:

# 通过 Supavisor 连接池(会话模式 — 支持 SET LOCAL)
postgresql://postgres.PROJECTREF:[email protected]:5432/postgres

# 直接连接(用于迁移)
postgresql://postgres:[email protected]:5432/postgres

环境变量

# 运行时查询(通过 Supavisor 连接池)
DATABASE_URL="postgresql://postgres.PROJECTREF:[email protected]:5432/postgres"

# 仅迁移(直接连接)
DIRECT_URL="postgresql://postgres:[email protected]:5432/postgres"

Prisma 数据源与迁移配置

datasource db {
  provider = "postgresql"
}
const runtimeDatabaseUrl = process.env.DATABASE_URL ?? "";
const migrationDatabaseUrl = process.env.DIRECT_URL ?? process.env.DATABASE_URL;

通过 Supavisor 的连接池

Supabase 的 Supavisor 支持事务模式(端口 6543)和会话模式(端口 5432)。使用会话模式(上方连接池 URL 中的端口 5432)确保 RLS 的 SET LOCAL 语句正常工作。

如果在事务模式(端口 6543)下使用 Supavisor,SET LOCAL 用于 RLS 时将不会在同一逻辑请求的各语句之间持久。使用 Supabase 且依赖 withRls 时,始终使用会话模式(端口 5432)。

使用 Supabase 运行迁移

迁移与 Neon 完全相同:

pnpm db:migrate

Prisma 使用 DIRECT_URL 执行 DDL 语句,使用 DATABASE_URL 执行所有其他查询。

PlanetScale Postgres 是 Nebutra 支持的 PlanetScale 路径。它保留同一个 Prisma PostgreSQL 数据源,并使用 PlanetScale 的 Postgres PgBouncer 端点承载运行时流量。

为什么选择 PlanetScale Postgres

  • 兼容 PostgreSQL 的 runtime — 保持 Sailor 对 Prisma、RLS 和 pgvector 的假设
  • PgBouncer 端点 — 使用端口 6432 承载应用程序的连接池流量
  • 直连端点 — 使用端口 5432 运行 Prisma 迁移、introspection、备份和其他 DDL 密集型工作
  • 分支和运维能力 — 使用 PlanetScale 的托管分支、备份、指标和运维工具,不需要更改应用程序代码

启用 pgvector

Nebutra 的 AI 功能需要 pgvector 扩展。在第一次迁移之前,使用具备管理权限的 PlanetScale Postgres 角色启用它:

CREATE EXTENSION IF NOT EXISTS vector;

连接字符串格式

PlanetScale Postgres 对两种连接模式使用相同的 host、credentials 和 database name。端口决定连接模式,且必须启用 SSL。

# 通过 PgBouncer 连接池 — 用于应用程序查询
postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:6432/DATABASE?sslmode=require

# 直接 PostgreSQL — 用于迁移和 DDL
postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:5432/DATABASE?sslmode=require

环境变量

# 运行时查询(通过 PgBouncer 连接池)
DATABASE_URL="postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:6432/DATABASE?sslmode=require"

# 仅迁移(直接连接 — 绕过 PgBouncer)
DIRECT_URL="postgresql://ROLE.BRANCH_ID:PASSWORD@HOSTNAME:5432/DATABASE?sslmode=require"

Prisma 数据源与迁移配置

datasource db {
  provider = "postgresql"
}
const runtimeDatabaseUrl = process.env.DATABASE_URL ?? "";
const migrationDatabaseUrl = process.env.DIRECT_URL ?? process.env.DATABASE_URL;

通过 PgBouncer 的连接池

PlanetScale Postgres 的 PgBouncer 使用事务模式。将它用于常规 OLTP 应用查询;不要将连接池 URL 用于 schema 变更、长时间运行的分析、备份,或需要持久连接的 session-specific 功能。

RLS 租户上下文必须保持事务内作用域。Nebutra 的 withRls helper 在事务内部设置租户变量;新增代码不应依赖能跨连接池事务存活的 session 变量。

Prisma 迁移继续使用 direct URL。不要为了 PlanetScale Postgres 将 Nebutra 的 Postgres 迁移工作流改成默认 db push;checked-in migrations 仍然是事实来源。

使用 PlanetScale Postgres 运行迁移

迁移与其他 PostgreSQL 提供商相同:

pnpm db:migrate

Prisma 使用 DIRECT_URL 执行 DDL 语句,使用 DATABASE_URL 执行运行时查询。

选择提供商

标准NeonSupabasePlanetScale Postgres
分支是 — 每个分支独立数据库是 — 托管数据库分支
托管控制台基础版功能完整的 Studio UI带指标和分支的运维控制台
连接池PgBouncer(事务模式)Supavisor(会话 + 事务模式)PgBouncer(事务模式,端口 6432
直连迁移 URL直接 PostgreSQL URL直接 PostgreSQL URL端口 5432 的直接 PostgreSQL URL
内置认证否(使用 Clerk / Better Auth)是(如需要)否(使用 Clerk / Better Auth)
内置存储否(使用 @nebutra/uploads是(S3 兼容)否(使用 @nebutra/uploads
pgvector默认启用作为扩展提供作为扩展提供
Prisma 迁移工作流checked-in Postgres migrationschecked-in Postgres migrationschecked-in Postgres migrations

如果团队严重依赖每个 PR 的数据库环境,选择带数据库分支能力的提供商。如果希望有一个单一的可视化控制台来检查表和运行 SQL,Supabase Studio 很合适。如果团队已经在 PlanetScale 上运维,或希望采用它的 Postgres 运维模型,请为 Sailor 核心 runtime 使用 PlanetScale Postgres,而不是 PlanetScale Vitess/MySQL。

PlanetScale Vitess/MySQL future path

PlanetScale Vitess/MySQL 是不同的数据库目标,不是受支持 Postgres runtime 的连接字符串变体。未来如果为 Sailor 提供 Vitess/MySQL template,需要单独定义这些契约:

  • MySQL/Vitess Prisma schema,或生成出来的 schema variant
  • 兼容 MySQL 的 Prisma adapter 策略
  • relationMode 决策;如果使用 Prisma relation mode,还要为 relation scalar fields 显式补齐 @@index
  • 与 checked-in Postgres migrations 不冲突的 branch/deploy-request migration workflow
  • 替换 PostgreSQL-only 能力,例如 RLS 和 pgvector

在这个 template 存在之前,PlanetScale 部署请使用 PlanetScale Postgres。

常见问题

How is this guide?

目录