技术方案:先画数据与服务边界
用一张最小架构图决定哪些能力自建、哪些外包,以及数据在哪里流动。
技术选型不是比较框架排行榜,而是决定:哪些东西由你负责,出了问题在哪里找。
第一版先画边界,再选具体产品。
否则很容易买了一堆服务,却不知道数据经过了谁——等到用户问"我的文件存在哪"或者某个服务挂了,你才开始画这张图。
从主路径画数据流
按用户动作画一条线:
浏览器 → 应用服务 → 数据库 / 文件存储 → AI 或第三方接口 → 结果 → 用户
每个节点补四项信息:
- 输入和输出是什么
- 是否包含个人信息或用户文件
- 失败以后能否重试
- 由谁保存、保存多久
这张图不只是技术方案,也是后续隐私说明、成本核算和故障排查的起点。四份文档共用一张图,比分开写四遍准确得多。
第一版只保留必要组件
多数小产品的第一版只需要:
- 一个前端与服务端应用
- 一个关系型数据库
- 必要时增加对象存储
- 一个邮件或消息通道
- 一个支付通道
- 完成核心结果所需的 AI 或业务接口
缓存、消息队列、微服务、数据仓库、多区域部署,都要由真实瓶颈触发。"以后可能用到"不是引入组件的理由。
每个组件都有三份隐性成本:要配置、会出故障、要在排错时被排除嫌疑。
第三项最贵。五个组件的系统出问题时,你要依次确认每一层,而两个组件的系统你几乎立刻知道该看哪。
自建还是购买
用四个问题判断:
- 这项能力是不是产品差异所在
- 自建失败是否会造成安全或资金风险
- 供应商更换后,数据能不能导出
- 成本会不会随用量失控
登录、邮件、支付、文件存储通常优先用成熟能力;真正影响结果质量的核心流程,才值得保留更多控制权。
第二问是硬线。认证和支付这两块自己写,出问题的代价是账号被盗或资金损失,而这类代码的正确性很难靠测试覆盖。
想清楚"这个服务挂了会怎样"
给每个外部依赖填一行:
服务 | 挂了影响什么 | 用户看到什么 | 有没有降级方案第三列决定用户体验,第四列决定你半夜要不要起来。
常见的降级方案:
| 情况 | 降级做法 |
|---|---|
| 模型接口超时 | 排队后重试,明确告知处理中 |
| 邮件发不出去 | 记下待发送,稍后重试,不阻断注册 |
| 支付回调延迟 | 提供主动查询,不让用户以为钱丢了 |
| 文件存储不可用 | 拒绝新上传但不影响已有内容 |
最不能接受的是静默失败——用户以为成功了,实际什么都没发生。
幂等:允许重试的前提
任何会花钱或产生副作用的操作,都要能安全地重复调用一次。
需要处理的典型场景:用户重复点击提交、支付回调重复到达、任务超时后重跑、用户刷新页面。
最小做法:给每次操作一个由客户端生成的唯一标识,服务端按这个标识去重。
这件事在第一版就要做。事后补,你要处理已经产生的重复扣费和重复任务,那比一开始就做难十倍。
数据放在哪,谁能看到
三件事要在写代码前定:
- 用户上传的文件存在哪,保留多久,用户能不能删
- 密钥放在哪,见环境变量与密钥
- 发给第三方的内容包含什么,用户知不知道
第三项最容易出问题。如果用户的文档内容会被发给模型服务商,这件事必须写在隐私说明里,不能默认用户想得到。相关内容见隐私与安全。
记录关键技术决定
每个重要决定只写一小段:
决定:第一版使用单体应用和一个关系型数据库
原因:主流程短,当前人数少,需要事务和简单备份
替代:无服务数据库、文档数据库
重新评估条件:出现独立扩容需求或明确性能瓶颈没有"重新评估条件"的决定,很容易变成永远不敢改的历史包袱。 三个月后你不记得当初是深思熟虑还是随手选的,于是不敢动。
最小验收标准
技术方案完成时,你应该能回答:
- 用户数据和密钥分别放在哪里
- 第三方服务失败时用户看到什么
- 哪些步骤允许重试,怎样避免重复扣费或重复执行
- 数据库丢失后可以恢复到什么时间点
- 更换关键供应商时能带走什么
答不上来的项,先作为明确风险记录下来,不要用"上线后再说"掩盖。写下来的风险和没写下来的风险,区别在于前者你还记得它存在。
常见错误
先选技术栈再想数据流。 买了一堆服务,说不清数据经过谁。
为了扩展性提前加组件。 排错成本立刻上升。
自己写认证和支付。 出错代价是账号或资金。
没想过依赖挂了怎么办。 用户看到白屏或者更糟的静默失败。
不做幂等。 事后处理重复扣费。
发给第三方的内容没写进隐私说明。 合规和信任双重风险。
技术决定不写重新评估条件。 变成不敢动的历史包袱。
风险只在心里记着。 三周后完全忘记。
验收标准
- 画出了主路径数据流,每个节点补齐了四项信息
- 删掉了所有不直接服务主路径的组件
- 认证、支付、邮件、存储优先用了成熟能力
- 每个外部依赖都填了"挂了会怎样"和降级方案
- 花钱或有副作用的操作都做了幂等
- 用户文件的存放位置和保留期限已确定
- 发给第三方的内容已写进隐私说明
- 关键技术决定都记了原因和重新评估条件
- 答不上来的项已列为明确风险
本章动作
画出主路径的数据流图,删除所有没有直接服务于主路径的组件。然后给每个外部服务填一行"挂了会怎样"。