01 · 分层全景
六层栈:从运行时底座到接口横切
点步进器或图里的任意一层聚焦;下方详情会列出该层的真实依赖与选它的理由。上层依赖下层,越往上越贴近请求、越薄。
提示:悬停某一层看它的一句话定位,点击则展开该层的依赖清单与选型理由。
01
02 · 选型原则
四条不成文的规矩
这些原则不写在代码里,但决定了上面每一层为什么长这样。
单体优先,无独立后端
Next Route Handlers + Server Actions 同仓同进程,省一层网络与部署;要对外集成再开 MCP / Agent API Key,不为「后端」单独起一套服务。
类型贯通到库
Drizzle schema.ts 即类型源头,Zod 守外部边界,端到端 TypeScript,无 codegen 步骤——改一张表,编译器立刻在调用处报错。
凭据不明文落库
密码 bcrypt、AI 密钥 AES-256 加密后入库、危险操作走确认闸门。安全不靠自觉,靠结构——明文永不落盘。
一份 schema,两处运行
同一份 Drizzle schema:生产走 PostgreSQL、本地走 SQLite,本地零外部依赖起跑;查询避开方言特有语法,靠 ORM 抹平差异。
03 · 关键抉择
六个岔路口,选了什么、放弃了什么
每一条都有真实备选。列出来是为了让「为什么不是那个」也留痕。
ORM
| 选择 | Drizzle ORM |
| 备选 | Prisma |
| 理由 | SQL-first、无生成步骤、schema 即类型,pg + sqlite 双方言;轻到能塞进 serverless 冷启动。 |
PostgreSQL 驱动
| 选择 | postgres.js |
| 备选 | node-postgres(pg) |
| 理由 | 更快、标签模板 SQL;prepare:false + max:1 适配连接池 / serverless,不踩预处理语句缓存坑。 |
API 形态
| 选择 | Route Handlers + Server Actions |
| 备选 | 独立 Nest / Express 服务 |
| 理由 | 同仓同进程、共享类型、一键部署;对外集成才开 MCP + Agent API Key,不为「后端」单独起一套。 |
鉴权
| 选择 | Better Auth |
| 备选 | NextAuth / Clerk |
| 理由 | 自托管、drizzle adapter 存库、内置 2FA;无外部依赖与按量计费,账号数据全在自己库里。 |
数据库迁移
| 选择 | 手写 SQL 迁移 |
| 备选 | drizzle-kit push(生产) |
| 理由 | 生产用可审计的原生 SQL(含 pgvector / pg_trgm 扩展),drizzle-kit 只在本地开发用。 |
缓存 / KV
| 选择 | Upstash Redis |
| 备选 | 自建 Redis 实例 |
| 理由 | HTTP 协议、serverless 友好、免运维;只做缓存与轻状态,主数据永远以 PostgreSQL 为准。 |
04 · 完整选型清单
10 个域,一屏看全后端依赖
逐条取自 apps/web/src/server 与 package.json。颜色标出每个依赖在选型里的角色。
后端依赖面板
核心主干是自持的服务端逻辑;托管服务把横切外包;基建类是自托管基础设施与加密;虚线红 是仅本地或可替换项。
选型边界(known tensions)
- 全部塞进一个 Next 进程:好处是零网络、共享类型;代价是重活(长任务、批处理)只能靠
maxDuration与外挂队列,量大了要拆服务。 - 双方言(PG / SQLite)要靠纪律:查询一律走 Drizzle、避开方言特有语法;pgvector / pg_trgm 是 Postgres 独有,SQLite 模式下相关能力降级。
- 迁移是手写 SQL:可审计但需人肉保证与 Drizzle schema 同步,drizzle-kit 仅辅助本地。
- 缓存 / 限流依赖 Upstash 可用性:Redis 只做加速与轻状态,主数据永远以 PostgreSQL 为准,Redis 挂了不影响正确性。
- AI 供应商密钥虽 AES-256 加密,但密钥管理仍在应用层:轮换与泄露响应需要额外流程,当前靠确认闸门 + 全量落档兜底。