Both have their place. At Google, we use both — REST for simple CRUD, GraphQL for complex data requirements.
REST
GET /api/users/123
GET /api/users/123/posts
GET /api/users/123/posts/456/comments
// Problem: 3 requests for one page (N+1)
// Problem: Over-fetching (GET /users returns ALL fields)GraphQL
query {
user(id: "123") {
name
avatar
posts(limit: 5) {
title
comments(limit: 3) {
content
author { name }
}
}
}
}
// One request, exact data neededComparison
| Aspect | REST | GraphQL |
|---|---|---|
| Endpoints | Multiple | Single |
| Data fetching | Server decides shape | Client decides shape |
| Caching | HTTP caching built-in | Requires Apollo/Relay cache |
| File uploads | Native support | Requires multipart spec |
| Error handling | HTTP status codes | Always 200, errors in body |
| Learning curve | Low | Moderate |
| Tooling | Universal | Specialized (Apollo, Relay) |
When to Use REST
- Simple CRUD APIs
- Public APIs (easier to understand and cache)
- File upload/download heavy apps
- When HTTP caching is critical
When to Use GraphQL
- Complex, nested data requirements
- Multiple client types (web, mobile, TV) needing different data
- Rapid frontend iteration without backend changes
- When over-fetching is a real performance problem
The Middle Ground: tRPC
For TypeScript full-stack apps, tRPC gives you end-to-end type safety without a schema language. It's REST-like simplicity with GraphQL-like developer experience.