为什么我们放弃了 GraphQL,回到了 REST
Why We Abandoned GraphQL and Went Back to REST
| David Wang | 2026-08-13T14:20:02
用了一年 GraphQL,最后还是回到了 REST。这篇分享我们的决策过程,以及 GraphQL 在什么场景下才真正值得用。
After a year with GraphQL, we switched back to REST. Sharing the decision process and when GraphQL is truly worth using.
## 一年前的决定 一年前我们决定在新项目里用 GraphQL,理由很充分: 1. 前端可以按需查询,减少 Over-fetching 2. 强类型 Schema,前后端契约明确 3. 一个端点搞定所有查询,不用设计一堆 REST URL 4. Playground 自带文档,不用写 Swagger 听起来很美好。实际用起来呢? ## 遇到的问题 ### 问题一:N+1 查询 这是 GraphQL 最经典的坑。 ```graphql query { orders(limit: 20) { id user { name email } # 每个 order 查一次 user items { # 每个 order 查一次 items product { name price } # 每个 item 查一次 product } } } ``` 20 个订单 → 20 次查 user + 20 次查 items + N 次查 product。一个查询背后可能执行了上百条 SQL。 是的,DataLoader 可以解决。但 DataLoader 的实现和维护成本不低。每个关联关系都得写一个 Loader,还得处理缓存失效。 ### 问题二:缓存困难 REST 的缓存天然好做: ``` GET /api/orders/123 Cache-Control: max-age=300 ETag: "abc123" ``` HTTP 层面的缓存机制直接可用。CDN、浏览器、反向代理都能参与缓存。 GraphQL 呢?所有请求都是 `POST /graphql`,body 里带查询语句。HTTP 缓存完全失效。你得自己实现应用层缓存,按查询语句做 key——复杂度瞬间上了一个台阶。 ### 问题三:安全和性能控制 REST 的每个端点可以独立做限流、权限控制、监控。 GraphQL 的一个端点可以查任何数据,这带来了几个问题: ```graphql # 恶意查询:深度嵌套 query { user { orders { items { product { reviews { author { orders { ... } } } } } } } } ``` 你需要额外实现: - 查询深度限制 - 查询复杂度分析 - 字段级权限控制 - 查询白名单(Persisted Queries) 这些 REST 里根本不需要考虑。 ### 问题四:团队学习成本 GraphQL 的学习曲线比想象的陡。不是学 GraphQL 语法(那很简单),而是学习: - Schema 设计最佳实践(接口、联合类型、输入类型) - Resolver 的优化(DataLoader、批量查询) - 错误处理(GraphQL 的错误模型和 REST 完全不同) - 分页(Cursor-based、Relay Specification) - 文件上传(GraphQL 原生不支持,需要额外方案) 团队 6 个人,真正能独立设计 GraphQL Schema 的只有 2 个。 ### 问题五:工具链还不够成熟 生成代码、Mock 数据、测试工具……GraphQL 的工具链虽然在进步,但和 REST 的生态(Swagger、Postman、各种代码生成器)比还差得远。 ## 回到 REST 后 我们把之前 GraphQL 的"好处"用 REST 的方式实现了: 1. **Over-fetching** → 用 `?fields=id,name,email` 字段过滤 2. **强类型契约** → OpenAPI 3.1 + 代码生成 3. **文档** → Swagger UI(比 GraphQL Playground 更成熟) 4. **前端灵活查询** → BFF 层按页面需求封装 API ## 什么时候 GraphQL 真正合适 说了这么多,GraphQL 不是坏技术,是**我们的场景不适合**。 适合 GraphQL 的场景: 1. **多端差异大**:Web、iOS、Android 对同一数据的需求差异很大 2. **数据关系复杂**:社交网络、知识图谱这类图状数据 3. **公共 API**:GitHub、Shopify 用 GraphQL 是因为第三方开发者的查询需求不可预测 4. **前端驱动的团队**:前端能力强,后端愿意配合 不适合的场景: 1. **内部 API**:前后端在一个团队,沟通成本低 2. **CRUD 为主**:简单的增删改查,REST 更直接 3. **性能敏感**:GraphQL 的灵活性是以性能控制为代价的 4. **团队对 GraphQL 不熟**:学习成本是真实的 ## 教训 技术选型不要追新,要追"合适"。GraphQL 很酷,但对我们的团队和业务来说,REST + OpenAPI 就够了。
After a year with GraphQL, we switched back to REST due to: N+1 query problems (DataLoader complexity), HTTP caching impossibility (all POST to single endpoint), security/performance control difficulty (query depth, complexity analysis), team learning curve (only 2 of 6 could design schemas independently), and immature toolchain. Replaced GraphQL benefits with REST: field filtering for over-fetching, OpenAPI 3.1 for typed contracts, BFF layer for frontend flexibility. GraphQL fits multi-client APIs with complex data graphs and unpredictable query patterns.