REST vs GraphQL vs gRPC: Choosing an API Style
Three API styles, three sets of trade-offs, no universal winner. Here is what each one is actually good at, what it costs, and how to choose, including mixing them.
REST, GraphQL and gRPC are not competing implementations of the same thing; they are three answers to different problems. REST is the general-purpose default, GraphQL solves client-driven data aggregation, and gRPC is built for strict, fast service-to-service communication. Picking well means knowing which problem you actually have.
REST vs GraphQL vs gRPC at a glance
| Aspect | REST | GraphQL | gRPC |
|---|---|---|---|
| Transport / format | HTTP + JSON | HTTP + JSON (usually one POST endpoint) | HTTP/2 + Protocol Buffers |
| Contract | OpenAPI (optional, external) | Typed schema, mandatory | Proto files, mandatory, code-generated |
| Over / under-fetching | Common, fixed with query params or endpoints | Client picks exactly the fields | Fixed messages, tight |
| HTTP caching | Native (ETag, Cache-Control) | Hard (POST), needs app-level caching | Not applicable |
| Streaming | SSE or workarounds | Subscriptions | First-class (client, server, bidirectional) |
| Browser support | Native | Native | Needs grpc-web and a proxy |
| Learning curve | Low | Medium, plus resolver performance | Medium, plus tooling and proxies |
REST: the reasonable default
REST maps resources to URLs and operations to HTTP verbs, and it gets you HTTP caching, a huge tooling ecosystem and a model every developer already understands, for free. For a public API, a mobile backend or a straightforward web app, REST done well (resources, versioning, consistent errors, pagination) is the right answer and the others are overhead.
GraphQL: client-driven aggregation
GraphQL earns its place when many different clients need many different shapes of the same data, and REST would force either dozens of endpoints or heavy over-fetching. The client asks for exactly the fields it needs in one request. The costs are real: HTTP caching mostly stops working, resolvers create N+1 database queries unless you add batching (DataLoader), and you need query depth and complexity limits or a single expensive query can take the server down. It also changes how you version: you deprecate fields rather than cut a v2.
gRPC: strict, fast, internal
gRPC uses Protocol Buffers over HTTP/2, with the contract defined in proto files and client and server code generated from them. It is compact, fast, and supports streaming in every direction. It is the right tool for service-to-service calls inside your system where you control both ends and want a tight, typed contract. It is a poor fit for a browser (it needs grpc-web and a proxy) and for a public API where consumers expect JSON.
You can mix them
The common production shape is not one style everywhere. A REST or GraphQL API faces the outside world, gRPC connects the services behind it, and where several clients need tailored data, a GraphQL layer sits in front as a backend-for-frontend that aggregates the REST and gRPC calls. Choose per boundary, not per system.
A decision guide
- ✓Public API, mobile backend, standard web app: REST.
- ✓One backend, many clients with very different data needs, aggregation across sources: GraphQL, and budget for caching and resolver performance.
- ✓Internal service-to-service, you own both ends, want a strict typed contract and streaming: gRPC.
- ✓Not sure: start with REST. You can add a GraphQL BFF or gRPC internally later without rewriting the API.
FAQ
- REST or GraphQL for a new API?
- Start with REST unless you have a specific reason not to. REST gives you HTTP caching, universal tooling and a familiar model. Choose GraphQL when many clients need many different shapes of the same data and REST would mean dozens of endpoints or heavy over-fetching, and you are ready to handle caching and resolver performance.
- Does GraphQL replace REST?
- No. They solve different problems. GraphQL is strong for client-driven aggregation across many clients; REST is simpler, caches natively, and is the better fit for public APIs and straightforward apps. Many systems use both: REST or GraphQL at the edge, and often a GraphQL layer that aggregates REST services behind it.
- When should I use gRPC?
- For service-to-service communication inside a system you control on both ends, where you want a strict typed contract, low overhead and streaming. It is not a good fit for browsers (it needs grpc-web and a proxy) or for public APIs where consumers expect JSON over plain HTTP.
- Is GraphQL slower than REST?
- Not inherently, but it is easier to make slow. A GraphQL query can trigger N+1 database calls in the resolvers unless you add batching, and an unbounded query can be very expensive, which is why depth and complexity limits are mandatory. REST pushes you toward one query per endpoint, which is easier to reason about.
- Can I use GraphQL and REST together?
- Yes, and it is common. A frequent pattern is REST services for the core domain and a GraphQL backend-for-frontend that calls them and shapes the response for each client. You can also expose the same data as both, though maintaining two contracts is extra work.
REST, GraphQL and gRPC are tools for different boundaries: the public edge, the client-aggregation layer, and the internal mesh. Most systems that pick well use more than one. When in doubt, REST is the safe starting point, and the others are additions you make when a specific need appears.
Need help with this topic? REST API Design
Discover this service →