9.4 KiB
Better Auth 接口响应时间优化设计
背景
cfw-auth 运行在 Cloudflare Worker 上,使用 Better Auth 和 Cloudflare D1 提供认证能力。当前项目已经接入账号中心相关插件,包括 username、phone-number、organization、api-key、expo、email OTP、two-factor、passkey、captcha 等。
本设计关注 Better Auth 接口响应时间优化,目标是在不重写 Better Auth adapter、不更换数据库、不改变客户端体验的前提下,先降低认证热路径延迟,并建立可观测的性能闭环。
范围
纳入范围:
/api/auth/get-session- 邮箱、用户名、手机号登录注册路径
/phone-number/send-otp/phone-number/verify- organization 邀请和接受邀请相关路径
/api-key/verify- Worker 层认证接口耗时观测
- Better Auth session 和 API key 插件的低风险性能配置
不纳入范围:
- 更换 D1 或重写 Better Auth database adapter
- 引入全新的缓存基础设施
- 改客户端 UI 或 Expo 客户端实现
- 改 Better Auth 认证语义
- 将 OTP 发送异步化
- 生产环境强制启用 Smart Placement 或 D1 read replication
成功标准
- 支持 session cookie cache,以减少 session 读取路径对 D1 的重复访问。
- 支持 API key 非关键更新延迟执行,以减少 API key 验证路径的同步写入成本。
/api/auth/*请求有结构化耗时日志,且不记录 token、cookie、API key、邮箱、手机号或请求体。- 性能配置都能通过配置关闭或调低。
- 本地
pnpm db:check、pnpm typecheck、pnpm test通过。 - 纯性能配置不应产生无关 D1 migration SQL 变化。
方案选择
推荐方案:低风险热路径优化 + 观测闭环
第一阶段只做三件事:
- 启用 Better Auth
session.cookieCache。 - 给
/api/auth/*增加轻量结构化耗时日志。 - 给
@better-auth/api-key配置deferUpdates,复用现有 Better Authadvanced.backgroundTasks.handler和 WorkerexecutionCtx.waitUntil。
这个方案改动小,能直接覆盖最可能的热路径瓶颈,也能为后续更重的 Cloudflare 平台优化提供证据。
备选方案:平台定位优化
开启 Cloudflare observability 和生产环境 placement.mode = "smart",通过线上 p50、p95、p99 对比验证 Worker 与 D1、外部 provider 的距离是否是主要瓶颈。
该方案保留为第二阶段,因为如果当前瓶颈是 session 查询、API key 写入或外部短信/邮件,仍需要第一阶段先拆清楚路径。
暂缓方案:存储层重构
引入 secondary storage、D1 read replication/Sessions API 或专门缓存层。该方向潜在收益高,但会增加一致性、安全和 adapter 适配复杂度。本次只记录决策门槛,不实施。
架构设计
保留现有三层架构。
第一层是 Worker/Hono 入口,由 src/index.ts 负责:
- CORS
/api/auth/*路由挂载- 把
executionCtx.waitUntil传给 Better Auth - 追加认证接口观测包装
第二层是 Better Auth 配置,由 src/auth.ts 负责:
database: env.DBsecretbaseURLtrustedOrigins- email/password 配置
- session 性能配置
advanced.backgroundTasks.handler- 插件列表
第三层是插件和外部服务适配,由 src/plugins.ts、src/email.ts、src/sms.ts 负责:
- Better Auth plugin 配置
- 邮件 provider
- SMS provider
- API key 性能配置
新增一个小型观测边界,例如 src/observability.ts。它只负责记录请求耗时,不参与认证语义,不改写 Better Auth 响应。
数据流
Session 读取路径
请求进入 Worker 后仍交给 Better Auth。启用 session.cookieCache 后,短 TTL 内的 session 数据可以从签名 cookie cache 读取,从而减少 D1 session 查询。
建议默认:
session: {
cookieCache: {
enabled: true,
maxAge: 300,
},
}
TTL 可以通过 env 配置。若安全策略要求更高,可以降到 60 秒或关闭。
OTP、邮件和短信路径
短信 OTP、验证邮件、密码重置邮件默认保持同步 await。这些路径的外部发送动作是用户感知成功的一部分,不能为了接口更快而提前返回成功。
后续可以异步化的仅限:
- 非关键通知
- 审计日志
- 分析事件
- 不影响用户下一步操作的后台同步
API key 验证路径
API key 的验证结果必须同步返回。请求计数、lastRequest、remaining 等非关键更新可以延迟执行。
@better-auth/api-key 提供 deferUpdates,并要求主 Better Auth 配置存在 advanced.backgroundTasks.handler。当前项目已经通过 Worker waitUntil 提供该 handler,因此可以将 deferUpdates 作为默认开启的性能配置。
一致性边界
可接受的短暂陈旧
session.cookieCache 可能导致 session 撤销、封禁、角色变化等状态在 TTL 内不立即反映。默认 TTL 不能过长,建议 300 秒起步,并允许配置为更短。
可接受的 eventual consistency
API key 计数和时间戳更新可以接受 eventual consistency。API key 是否有效、是否匹配、是否过期等核心判断仍必须同步完成。
不接受的提前成功
OTP 发送、验证邮件、密码重置邮件不应在 provider 未完成时提前返回成功。否则用户可能收到成功响应却拿不到验证码或链接。
配置策略
建议新增或使用以下配置:
-
BETTER_AUTH_SESSION_COOKIE_CACHE_MAX_AGE- 默认:
300 - 用途:控制 Better Auth session cookie cache TTL。
- 默认:
-
API_KEY_DEFER_UPDATES- 默认:
true - 用途:控制 API key 非关键更新是否延迟执行。
- 默认:
-
Cloudflare
observability- 建议写入
wrangler.jsonc - 初始
head_sampling_rate使用低采样,例如0.1
- 建议写入
-
Cloudflare
placement.mode = "smart"- 不作为本次强制配置
- 作为生产验证选项记录
非法配置处理:
- session cache TTL 非数字或小于等于 0 时使用默认值。
API_KEY_DEFER_UPDATES=false时关闭延迟更新;其他值按默认开启处理。
观测设计
结构化日志字段:
event: 固定为auth_requestmethodpath或归一化后的 endpointstatusdurationMscolo,来自request.cf?.colocfRay,来自请求头cf-ray
不得记录:
AuthorizationCookie- API key
- session token
- 请求体
- 邮箱
- 手机号
- OTP code
观测层失败时必须静默降级,不影响 Better Auth 响应。
错误处理
- Better Auth 业务错误保持原样返回。
- 观测层不能改写响应体、状态码或 header。
- 后台任务失败只记录错误,不回滚已经返回给客户端的响应。
waitUntil接收的 promise 必须捕获并记录错误,避免隐藏失败。
测试策略
配置单元测试
扩展现有 tests/auth-config.test.ts:
- 默认 session cookie cache TTL 是
300。 - env 可覆盖 TTL。
- 非法 TTL 使用默认值。
- API key defer 默认开启。
API_KEY_DEFER_UPDATES=false可以关闭。
Worker 行为测试
扩展现有 tests/auth-worker.test.ts:
/api/auth/*请求仍能正常返回。- 观测包装不改写 Better Auth 响应。
- 日志包含
durationMs、method、status。 - 日志不包含
cookie、authorization、手机号、邮箱、API key 等敏感信息。
本地验收
必须通过:
pnpm db:check
pnpm typecheck
pnpm test
如果本地 Worker 可运行,补充烟测:
curl -i http://localhost:8788/api/auth/get-session
curl -i http://localhost:8788/api/auth/reference
生产验证策略
本次不要求完成生产验证,但部署后应对比:
get-sessionp50、p95、p99api-key/verifyp50、p95、p99- OTP 发送路径 p95
- organization invitation 路径 p95
- Worker colo 分布
- D1 或外部 provider 是否主导尾延迟
只有当观测显示主要延迟来自远端等待时,再评估开启 Smart Placement。只有当 D1 读延迟明确成为瓶颈时,再评估 D1 read replication、Sessions API 或 secondary storage。
后续决策门槛
进入平台定位优化的门槛:
- 第一阶段上线后,p95 仍不能接受;
- 日志显示延迟主要来自 D1 或外部 provider;
- 多地域请求有明显延迟差异。
进入存储层重构的门槛:
get-session或 organization 读路径被证明确实受 D1 读延迟限制;- session cookie cache 无法满足安全或一致性要求;
- API key rate counter 写入仍是高频瓶颈;
- 有明确的强一致、弱一致、撤销语义设计。
风险
- session cookie cache 会引入短 TTL 内的撤销延迟。
- API key
deferUpdates会让计数类字段 eventual consistent。 - 观测日志若设计不当可能泄露敏感信息。
- 过早引入 secondary storage 会增加一致性复杂度。
- Smart Placement 可能改善后端等待,也可能对当前瓶颈帮助有限,必须用数据验证。
实施顺序
- 抽出性能配置解析函数。
- 在
src/auth.ts启用 session cookie cache。 - 在
src/plugins.ts为 API key 配置deferUpdates。 - 增加
/api/auth/*观测包装。 - 增加配置和 Worker 行为测试。
- 更新 operations 文档。
- 运行本地验证。
自检结论
- 无未完成标记或空白段落。
- 范围限定在第一阶段低风险优化,没有混入存储层重构。
- 架构、数据流、一致性、配置和测试互相一致。
- 每个可能引入安全或一致性变化的优化都有关闭或调低路径。