
写在前面:这篇文章的原文标题很扎心——「当你那『干净』的 REST API 变成生产环境噩梦」。读完之后发现说的就是我自己踩过的坑,所以忍不住转写了一下,原文链接附在顶部,感兴趣可以直接去看英文版。
纸面上看,一切都完美得不像真的:
然后一上线,傻眼了:
这时候才明白一个扎心的道理:
REST API 设计不是什么优雅活儿——本质上是在「不确定性下的契约设计」。

你以为在设计端点?
实际上你在设计的是——一份在重重不确定性下的契约。
真正影响你 API 设计的因素有哪些:
忽视这些,API 在规模面前就是纸糊的。
人人都知道 /users、/orders。
但这只是表面。
真正要问的问题是:
你的资源,生命周期是什么?
POST /orders
GET /orders/:id
PUT /orders/:id
DELETE /orders/:id
看起来很标准。放在真实系统里,完全不对。
为什么?
好一点的写法:
POST /orders
POST /orders/:id/pay
POST /orders/:id/ship
POST /orders/:id/cancel
这样做的好处:
大部分 API 在重试面前一击即溃。
现实是:
如果你的接口不具备幂等性 → 重复操作。
支付接口:
POST /payments
客户端超时 → 重试 → 扣了两次钱。
恭喜,用户信任-1。
POST /payments
Idempotency-Key: 8f3a-xyz-123
服务端逻辑:
if (exists(idempotencyKey)) {
return previousResponse;
}
processPayment();
storeResult(idempotencyKey);
你的 API 调用了:
其中一个挂了。
然后呢?
大多数 API:
返回 500,然后祈祷。
这不是策略,这是放弃。
例子:
{
"status": "partial_success",
"data": {...},
"failed_dependencies": ["inventory-service"]
}
很多团队的做法:
/v1/users
/v2/users
问题来了:
即使到了那个地步:
优先用 Header 做版本控制
Accept: application/vnd.myapi.v2+json

REST 的经典难题。
GET /users/:id
返回了:
客户端其实只需要姓名。
浪费了:带宽 + 延迟。
客户端需要:
结果发了 3 次请求。
延迟直接乘以 3。
GET /users/:id?include=orders,payments
代价:

来一个 Express.js 示例:
const express = require('express');
const app = express();
// 中间件:每个请求带上 ID,方便追踪
app.use((req, res, next) => {
req.id = crypto.randomUUID();
next();
});
// 幂等性中间件
const store = new Map();
app.post('/payments', async (req, res) => {
const key = req.headers['idempotency-key'];
if (store.has(key)) {
return res.json(store.get(key));
}
const result = await processPayment(req.body;
store.set(key, result);
res.json(result);
});
// 显式状态转换
app.post('/orders/:id/ship', async (req, res) => {
const order = await getOrder(req.params.id);
if (order.status !== 'paid') {
return res.status(400).json({ error: 'Invalid state' });
}
await shipOrder(order);
res.json({ status: 'shipped' });
});
你忽略了:
你的系统平时挺好……直到网络抖动来敲门。
没有:
调试就变成了猜谜。
改数据库 → API 跟着挂
正确的认识是:
API 是一份契约,不是数据库的镜子
有人这样做:
200 OK(body 里其实装着错误)
或者:
所有情况都返回 500
两种都是反模式。

如果你的 API:
那它根本不是生产就绪的。
如果你设计 API 的时候假设一切都会正常运行,那你的系统在它不正常运行的那一刻,就会崩溃。