最近给个人站搭后端,选了 Vercel + Node.js + TiDB 的组合,踩了一些坑,记一下。
问题:Vercel Functions 不能直连 MySQL
Vercel 的函数是无状态的:
- 每次冷启动都新建一个函数实例
- 实例临时存在(几秒到几分钟)
- 每个实例都要建立自己的 MySQL 连接
如果用户请求一多,函数实例数会飙升,TiDB 的连接数会被瞬间打爆。免费档集群一般只允许 100-200 个并发连接。
思路:换协议,绕开连接池
MySQL 协议是长连接,但 TiDB 提供了基于 HTTPS 的 Serverless 驱动 (@tidbcloud/serverless):
import { connect } from "@tidbcloud/serverless";
import { drizzle } from "drizzle-orm/tidb-serverless";
const client = connect({ url: process.env.TIDB_CONNECTION_URL });
export const db = drizzle(client, { schema });
每次查询都走一次 HTTPS 请求,无状态,不需要连接池。Vercel 函数天然适配。
Vercel 部署的几个细节
1. 环境变量
TIDB_CONNECTION_URL=mysql://USER:PASS@gateway01.REGION.prod.aws.tidbcloud.com:4000/DB?ssl=true
AUTH_SECRET=$(openssl rand -base64 32)
2. 不能用 middleware.ts 跑 Drizzle
Next.js 16 的 proxy.ts(原 middleware.ts)跑在 Edge Runtime,不支持 Node native modules,Drizzle 客户端在那里会炸。
要拆成两个配置:
auth.config.ts:Edge-safe,只做 JWT 校验和路由守卫auth.ts:完整配置,带 Drizzle adapter,跑在 Node Runtime 的 API route 里
3. TiDB Cloud 区域选择
选 hkg / sin / tok,比 us-east 离中国大陆近。冷启动 + HTTPS 查询总共 < 200ms。
写在最后
这套组合对个人站非常合适:Vercel Hobby 完全够用(100 GB 流量/月),TiDB Cloud Serverless 免费档(每月 5M Request Units)也是个人站级别。
代码在 https://github.com/... (TODO: 等开源了放链接)。