基于 Better Auth 和 Drizzle 的 Next.js Boilerplate:为什么这是 SaaS 最值得长期押注的技术栈

September 6, 2026
为什么用 Better Auth + Drizzle ORM 搭建的 Next.js boilerplate 更经得起时间考验:已核实的特性、与 NextAuth/Prisma 的公平对比,以及 NEXTY.DEV 的接线方式。
Next.js Techniques
Database

两个几乎无法低成本回头的决定

SaaS boilerplate 里的大部分东西都可以换。换 UI 组件库、换邮件服务商、从 Vercel 搬到 VPS,麻烦归麻烦,最多一周。但有两样不是这样:认证层和 ORM。一个基于 Better Auth 和 Drizzle 的 Next.js boilerplate,押的正是这两样,所以在把十二个月的产品建在上面之前,值得先弄清楚这笔押注押的是什么。

认证难换,是因为 usersessionaccount 三张表被所有东西引用:订单、积分、文章、审计日志、团队成员关系。ORM 难换,是因为代码库里每一条查询都是对着它写的,迁移历史也绑在它的工具链上。NEXTY.DEV 亲身经历过一次:v3.0.0 从 Supabase Auth 和 Supabase Database 切换到了 Better Auth 和 Drizzle ORM。这篇文章存在的理由就在这里:我们知道切换的代价是什么,也知道为什么不会再切回去。

Better Auth 给 SaaS boilerplate 带来了什么

Better Auth 对自己的定位是:面向 TypeScript 的、框架无关的通用认证与授权框架。核心提供邮箱密码和社交登录,其余一切都是插件。一个 SaaS 真正需要的部分,以下全部对照官方文档核实过:

  • Magic link:向用户邮箱发送一个链接,点击即完成认证,不涉及密码。
  • Email OTP:向邮箱发送一次性验证码,可用于登录、邮箱验证和密码重置。
  • Google One Tap:通过 Google One Tap API 一键登录,客户端与服务端逻辑由插件处理。
  • 两步验证:认证器 App 的 TOTP、邮件或手机 OTP、用于恢复的备份码、受信设备。
  • Organization:组织、成员、带过期时间的邮件邀请、三个默认角色(owner、admin、member)、自定义角色、team,以及可扩展的访问控制系统。
  • Admin:创建用户、修改角色、封禁与解封(临时或永久)、模拟登录、用户列表、撤销会话。

底层的设计原则是「你的认证代码住在你自己的代码库里」。Better Auth 写入四张由你持有的核心表(user、session、account、verification),加上你启用的插件所需的表,并通过 npx auth@latest generate 为你的 ORM 生成 schema。

它替代了什么,以及公平的取舍

NextAuth / Auth.js。 Auth.js 是一个成熟的、运行时无关的库,提供 100 多个 OAuth provider,以及 Prisma、Drizzle、Supabase、Kysely 等适配器,支持 OAuth、magic link、credentials 和 WebAuthn。两者的差别在于 SaaS 专属层的深度:Auth.js 给你的是 session 和 user,组织、角色、封禁、2FA、模拟登录都要自己搭。另一个实际差别是会话策略。Auth.js 在未配置数据库适配器时默认使用 JWT session,其文档也坦率承认「在编码的过期时间之前让 JWT 失效是不可能的」,除非维护服务端黑名单;而数据库 session「可以随时在服务端修改」,代价是一次数据库往返。Better Auth 默认就是数据库 session,SaaS 管理员封禁一个用户并要求立即生效时,你要的正是这个。

托管认证(Supabase Auth、Clerk、Auth0)。 托管服务的合理理由是有人替你运维:密码哈希、OAuth 回调的边缘情况、邮件送达率,以及一个客服团队第一天就能用的后台。代价是用户身份存在别人的 schema 和别人的计费档位里,每一个碰到用户的产品功能,最终都要多一次网络跳转或者维护一份影子副本。用 Better Auth,user 表就是你 Postgres 里的一张普通表,可以和 orderscredit_transactions 在一条查询里 join。对一个本来就在运维数据库的小团队来说,这是更少的基础设施,而不是更多。

具体到 SaaS 的需求:社交登录、给讨厌密码的人一条无密码路径、管理后台的角色、随时干掉一个会话的能力、以及迟早会来的团队功能。Better Auth 在不离开你代码库的前提下覆盖了这五项。

Drizzle ORM 给 SaaS boilerplate 带来了什么

Drizzle 自己的说法是「会 SQL 就会 Drizzle」。它是一个零依赖的 TypeScript ORM,约 31 KB,自称 serverless-ready by design,通过标准驱动运行在 PostgreSQL、MySQL、SQLite 等数据库之上。schema 就是 TypeScript,查询构建器贴着 SQL 走,关系查询 API 只会编译出一条 SQL。迁移来自 drizzle-kitdrizzle-kit generate 把 schema 与上一份快照做 diff 并生成 SQL,drizzle-kit migrate 负责执行。

一张表和一条查询,没有任何花哨的东西:

import { pgSchema, text, timestamp, integer, uuid } from 'drizzle-orm/pg-core'
import { eq, desc } from 'drizzle-orm'

// 每个项目一个 Postgres schema,多个应用可以共用一个数据库
export const app = pgSchema('myapp')

export const orders = app.table('orders', {
  id: uuid('id').primaryKey().defaultRandom(),
  userId: text('user_id').notNull(),
  amountCents: integer('amount_cents').notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
})

// 完整类型推导:返回 { id: string; userId: string; amountCents: number; createdAt: Date }[]
const recent = await db
  .select()
  .from(orders)
  .where(eq(orders.userId, session.user.id))
  .orderBy(desc(orders.createdAt))
  .limit(20)

SaaS 场景下的 Drizzle vs Prisma

Prisma 是另一个严肃的选项,而且是个好选项。它有自己的声明式 schema 语言、自动生成的类型安全 client、Prisma Migrate 和 Prisma Studio;文档写明 Prisma Client 可以运行在任何受支持的 Node.js 或 TypeScript 后端,包括 serverless。Prisma 的运行时在过去两年变化很大,如果你读到的是一篇围绕引擎二进制展开的旧对比,请先到 prisma.io 针对你的目标运行时重新核实再做决定。

日常真正有影响的差别是哲学。Prisma 把 SQL 藏在自己的查询语言和 schema 文件后面;Drizzle 让你离 SQL 只有一步,schema 就是普通的 TypeScript,定义表的那个文件同时导出类型,还能在不离开语言的情况下写索引、部分索引和 ON DELETE 语义。对一个要写 credit_transactions 账本、带序列列和 next_grant_at 部分索引的 SaaS 来说,贴近 SQL 不再是风格偏好,而是实用需求。

为什么两者搭配得好

都是 TypeScript 优先。都把数据放在你自己的数据库里,中间没有供应商。而且 Better Auth 有官方的 Drizzle 适配器:drizzleAdapter(db, { provider: 'pg' }),附带 schema 选项把 Better Auth 的模型映射到你的 Drizzle 表。适配器要求表名对应,CLI 会替你生成 Drizzle schema,于是认证表就成了和计费表同处一个 schema.ts 的普通表。一份迁移历史、一套类型、一个查找的地方。

NEXTY.DEV 如何把 Better Auth 和 Drizzle 接起来

NEXTY.DEV 是一个 Next.js SaaS boilerplate,从 v3.0.0 起就在生产环境跑这套组合。changelog 里写的理由是:离开 Supabase Auth 是为了更大的灵活性,从 Supabase Database 换到 Drizzle 是为了更好的开发体验;两条都站住了。

认证方式。 Google 和 GitHub OAuth、email OTP 和 magic link,表单上挂 Cloudflare Turnstile,登录有 IP 和按用户的限流。Better Auth 的 admin 插件支撑管理后台:用户角色、封禁(同时清掉被封用户的会话)、带来源归因的用户列表。需要团队功能时 organization 插件直接接进同一份配置;nexty.dev 自己就用它跑带席位上限的团队邀请。服务端暴露了小巧的守卫(getSessionisAdmin),受保护页面和 server action 不必各自重写会话检查。唯一需要你生成的密钥是 BETTER_AUTH_SECRETBetter Auth secret 生成器可以在浏览器里直接生成。

数据库。 填好 DATABASE_URL,连接工厂会按平台和数据库提供商挑选连接池参数。支持 Supabase、Neon 和自托管 Postgres;走 Supabase 的 pooled 连接时会自动禁用 prepared statements,这很重要,因为 PgBouncer 的 transaction 模式否则会静默失败。所有表,包括认证表,都在一个 schema.ts 和一个 drizzle-kit 迁移目录里。

Schema 隔离。 每张表都声明在 pgSchema('nexty') 之下而不是 public,多个项目可以共用一个 Postgres 实例而不发生表名冲突,把项目在数据库之间搬迁也只是一次 schema dump,而不是一场手术。完整流程见数据库 schema 隔离与迁移

SaaS 的其余部分。 Stripe(以及 Creem、PayPal),订阅、一次性付款和积分账本;next-intl 开箱支持 en、zh、ja;带多语言文章的 CMS;Resend 或 Cloudflare Email Sending;R2 文件存储;AI SDK 示例。Pro 授权是一次性 $188,终身更新,并获得私有源码仓库的访问权;开源版是免费的功能受限启动模板,包含国际化、邮件订阅、分析和静态博客,但不含数据库、认证和支付。详情见定价介绍文档

已经在用 Supabase Auth 或 NextAuth 的团队:迁移注意事项

现实一点:这是一次数据迁移加一次代码迁移,而数据是容易的那一半。

从 Supabase Auth 迁移。 导出 auth.users 和 identities,插入 Better Auth 的 useraccount 表(每个绑定的 provider 一行 account)。问题在密码哈希:Supabase 存的是 bcrypt,Better Auth 默认 scrypt。要么配置 Better Auth 的密码哈希去校验旧格式,要么在首次登录时通过 magic link 强制重置。session 不迁移,所有人重新登录。把时间预算最多留给替换 supabase.auth.getUser() 调用和依赖 RLS 的查询,因为 Drizzle 直连 Postgres,基于 auth.uid() 的 RLS 策略不再生效。

从 NextAuth / Auth.js 迁移。 表结构很接近(user、account、session、verification token),一个列映射脚本能覆盖大部分。如果原先是 JWT session,就没有东西要迁,用户重新认证即可。更大的成本在代码:每一个 getServerSessionuseSession 都要换成 Better Auth 的调用,你额外拼上去的角色逻辑要换成 admin 插件的 role 字段。

无论哪种。 先在一个独立的 Postgres schema 里跑新的认证,迁一份副本,比对行数,再切 DNS。对一个典型 SaaS 来说这是两到五天的活,不是一个下午。

FAQ

和 NextAuth 相比,Better Auth 可以上生产吗?

两者都在生产环境被使用。Auth.js 历史更长、provider 列表更广;Better Auth 内置的 SaaS 层更深(组织、admin、2FA、封禁),且默认数据库 session。按你想自己持有什么、想自己搭什么来选。

Drizzle 只能配自托管 Postgres,还是也能用 Supabase 或 Neon?

三者都可以。Drizzle 运行在标准的 Postgres 驱动之上。唯一和提供商相关的细节是 Supabase 的 pooled 连接串需要禁用 prepared statements,NEXTY.DEV 已经替你处理。

Better Auth + Drizzle 的 boilerplate 能跑在 serverless 和 Cloudflare Workers 上吗?

Drizzle 是 serverless-ready by design,Better Auth 是框架无关的。NEXTY.DEV 可部署到 Vercel、Cloudflare Workers、Dokploy 和 Coolify;Workers 路径通过 HTTP 驱动或 Hyperdrive 连接数据库。

授权模式是什么?

Pro 是一次性支付 $188,终身更新;你会被邀请为私有仓库的协作者,并持续获得后续版本。

结语

如果你在 2026 年启动一个 SaaS,希望用户身份和数据留在自己的 Postgres 里,类型从 schema 到查询到 session 一路跟着你走,Better Auth 加 Drizzle 是我们会再选一次的组合。NEXTY.DEV 把这个选择连同支付、国际化、CMS 和管理后台一起打包接好。读一读介绍,比较一下套餐,从一份你不必推翻重来的 schema 开始。