REST, GraphQL, or gRPC: Picking by Use Case, Not Trend
Choose between REST, GraphQL, and gRPC by the caller you are building for, not by trend: REST suits public APIs, GraphQL suits frontends with many data shapes, and gRPC suits fast internal service calls. A public partner API, an internal service mesh, and a mobile client on a flaky connection have almost nothing in common as consumers.
A public partner API, an internal service mesh, and a mobile client with a flaky connection have almost nothing in common as consumers, and each protocol was designed with a different one of those callers in mind. This breaks down the real tradeoffs by use case instead of by hype cycle.
Which API style fits who's calling: REST, GraphQL, or gRPC?
Before comparing protocols, answer three questions about the caller: do you control both ends of the connection, does the client need exactly the fields it asks for or is a fixed response shape fine, and does the connection need to survive high latency or spotty connectivity. A third-party integrator you don't control, an internal service you fully own, and a mobile app on an unreliable network need different answers to all three, and the protocol that's right for one is often wrong for another.
Teams that pick a single protocol for every API in the company usually end up forcing a bad fit somewhere, most often GraphQL bolted onto a simple internal service that never needed flexible querying, or REST stretched across a mobile client that keeps re-requesting the same nested data.
REST: Still the Right Default for Public APIs
REST wins on what matters most for a public or partner-facing API: it's cacheable at the HTTP layer without extra tooling, every API client and monitoring tool already understands it, and a partner integrating against your API doesn't need to learn a new query language to make a first successful call. Documentation, rate limiting, and versioning all have well-worn patterns that don't require explaining a different query language to an external team.
Its real weakness is overfetching and underfetching: a mobile client often gets more fields than it needs from one endpoint and has to make several more calls to assemble a full screen's worth of data. That's a real cost, but for most public APIs it's a smaller cost than the integration friction of asking every partner to learn GraphQL or protocol buffers just to call your API.
GraphQL: Solves Overfetching, Creates New Problems
GraphQL's core promise holds up: a client asks for exactly the fields it needs across multiple resources in one request, which genuinely helps a mobile app or a frontend with many different views over the same underlying data. Where it costs you is on the server side. A single GraphQL endpoint means you lose HTTP-layer caching by default, every resolver needs its own care to avoid the N+1 query problem, and a client can accidentally request a deeply nested query that's expensive to compute even though it looks like a simple request.
It fits best when you control the client and the schema evolves together with a frontend that has many different data shapes to serve, an internal product API behind a web and mobile app, for example. It fits worst as a public API for third parties you don't control, where an unrestricted schema is also a real cost surface you have to actively defend.
gRPC: Fast Internal Calls, a Steep Cost at the Edge
gRPC's binary protocol and generated client code make service-to-service calls inside your own infrastructure fast and strongly typed, catching a mismatched field at compile time instead of in production. For internal microservices talking to each other, that combination is hard to beat.
It's a poor fit at the browser or mobile edge. Browsers don't support raw gRPC without a proxy layer like gRPC-Web, which reintroduces complexity you were trying to avoid, and debugging a binary protocol with standard HTTP tools is harder than reading a REST or GraphQL request. Keep gRPC inside your service mesh where you control every caller, and use REST or GraphQL at any boundary a browser, a partner, or a client you don't fully control touches directly.
How do you quickly decide between REST, GraphQL, and gRPC?
When you're not sure, work through these in order:
- If the caller is external and you don't control their client, default to REST unless you have a specific, proven reason not to.
- If the caller is your own frontend across web and mobile with many different data shapes, GraphQL is worth the operational cost.
- If the call is service-to-service inside infrastructure you fully control, gRPC's speed and type safety are usually worth adopting.
- If you're still unsure, pick REST. It's the easiest to migrate away from later and the hardest one to get badly wrong.
The wrong choice isn't usually catastrophic, it's a slow tax: more integration support tickets with REST stretched too thin, more resolver bugs with GraphQL adopted too early, more debugging friction with gRPC pushed out to a client that was never meant to speak it.
What Good Looks Like
A good protocol choice means the decision was made per caller, external partner, internal service, or mobile client, rather than one protocol applied company-wide regardless of fit.
Building The Capability (5-Stage Skill Ladder)
How to Get Started
Frequently Asked Questions
Can we mix protocols instead of picking just one?
Yes, and most companies at any real scale do. A common pattern is REST or GraphQL at the edge for browsers and partners, with gRPC between internal services. The mistake isn't mixing protocols, it's picking one protocol for every use case regardless of who's actually calling it.
Is GraphQL worth it for a small internal API?
Usually not. GraphQL's benefits show up when a frontend has many different data shapes to serve across web and mobile. For a small internal service with one or two consumers and a simple, stable response shape, REST is less operational overhead for the same result.
Why can't browsers call gRPC directly?
Browsers don't support the streaming mechanics gRPC relies on, so calling it from a browser requires a proxy layer like gRPC-Web that translates the request. That extra layer is usually why teams keep gRPC to internal, service-to-service calls instead of exposing it at the edge.
About the numbers
This guide doesn't quote a sourced benchmark. Figures in it are estimates or general guidance, so check them against your own numbers.
Related Guides
REST, GraphQL, or gRPC: Choosing by Workload
REST, GraphQL, and gRPC solve different problems. A decision rule for which one fits a public API, a mobile client, or service-to-service calls.
Picking Between REST, GraphQL, and gRPC for a New Service
A decision guide for choosing REST, GraphQL, or gRPC for your next service, based on who's calling it and what actually slows each one down.
gRPC, GraphQL, or REST: What Actually Breaks Each One at Scale
REST, GraphQL, and gRPC each fail differently under real production load. A comparison of the specific tradeoffs that matter once you are past a prototype.
GraphQL, REST, or gRPC: Match the Protocol to the Caller
REST for public APIs, gRPC for internal services, GraphQL for aggregation: a practical way to pick, plus the N+1 and schema-drift traps in each.
GraphQL, REST, or gRPC: Picking an API Style by Use Case
A side-by-side comparison of GraphQL, REST, and gRPC for internal and external APIs, with the tradeoffs that actually matter when choosing between them.
GraphQL, REST, or gRPC: How to Actually Choose
Compare GraphQL, REST, and gRPC on client flexibility, caching, tooling, and internal versus external use, so you can pick the right API style.