Picking Between REST, GraphQL, and gRPC for a New Service
Choose REST for public APIs and third-party integrations, GraphQL when a frontend needs to shape queries across nested resources, and gRPC for high-volume service-to-service calls you control. The right protocol depends on who is calling the API and how those calls are shaped, not on which protocol is newest.
REST, GraphQL, and gRPC solve different problems well enough that most companies of any size end up running more than one, on purpose, for different parts of their system.
What each protocol is actually good at
REST is good at being understood by anyone, cached by ordinary HTTP infrastructure, and debugged with nothing more than a browser or curl. That's why it remains the default for public APIs and anything a third party will integrate against.
GraphQL is good at letting a frontend ask for exactly the fields it needs across several resources in one round trip, which matters most when your client is a mobile app on a slow connection or a dashboard that renders dozens of small widgets. gRPC is good at low overhead, strongly typed contracts, and streaming, which is why it dominates service-to-service calls inside a single infrastructure.
The N+1 problem GraphQL doesn't solve for you
GraphQL's flexibility on the client side pushes a real cost onto the server: a query that asks for a list of orders and each order's customer can trigger one database call per order if your resolvers aren't written carefully, the classic N+1 pattern. GraphQL itself doesn't prevent this. A batching layer, typically a dataloader pattern that groups requests within a single tick, does.
Skipping that layer is the most common reason a GraphQL API that performs fine in development falls over under real traffic, because the query shapes that expose the problem are exactly the ones a flexible schema invites clients to write.
Where gRPC's performance advantage matters, and where it doesn't
gRPC's binary protocol and generated clients cut serialization overhead and give you a contract that breaks the build instead of breaking in production when a field changes type. That advantage matters most at high call volume between services you control, where shaving overhead per call adds up.
It matters far less for a handful of calls a minute, or for anything a browser needs to call directly, since browser support for gRPC is limited without a proxying layer. Reaching for gRPC because it's fast, for a service that makes a few dozen calls a day, adds tooling cost without a real payoff.
The generated client and server stubs are the part teams underestimate. They remove an entire class of bug where one side of a call changes a field's meaning without the other side noticing, but they also mean every schema change needs a code generation step wired into your build, which is one more thing that can be misconfigured on a new engineer's first day.
A decision rule for your next service
Ask who the caller is first. A third party or a public integration points to REST. A frontend that needs to shape its own queries across nested resources points to GraphQL. A service calling another service you both control, especially with high volume or a need for streaming, points to gRPC.
REST, GraphQL, and gRPC all support the same on-demand deployment habits that put a team in DORA's highest-performing cluster, but only if your contracts don't break every time a client updates1. Whichever protocol you choose, versioning discipline matters more to your deploy cadence than the protocol itself does.
Match the protocol to the caller like this:
- Pick REST when the caller is a third party or a public integration, since it is widely understood and works with ordinary HTTP caching.
- Pick GraphQL when a frontend needs to ask for exactly the fields it wants across several resources in one round trip.
- Pick gRPC when one service calls another that you control, especially with high volume or a need for streaming.
- Expect to run more than one protocol, with a gateway translating between them at the edge.
What changes once you have external customers
Internal flexibility gets harder to justify once a contract has customers outside your own team depending on it. A GraphQL schema that a partner queries in unexpected ways becomes something you can't casually restructure. A gRPC contract with an external partner requires them to regenerate clients on your schedule, not theirs. REST's looser contract, ironically, is often the easiest one to evolve without breaking someone you don't control.
This is also where deprecation policy starts to matter as much as the protocol choice itself. A field you remove from an internal gRPC contract is a same-day fix across your own services. The same removal on a public REST or GraphQL API needs an announced sunset window, because you can't force an external integrator to redeploy on your timeline.
What Good Looks Like
Good protocol choice means each API in the system was picked for who calls it, and that reasoning is written down somewhere a new engineer can find it.
Building The Capability (5-Stage Skill Ladder)
How to Get Started
Frequently Asked Questions
Should we rewrite our REST API in GraphQL?
Only if you have a specific problem GraphQL solves, like a frontend making many round trips to assemble one screen. Rewriting a working REST API for its own sake usually costs more than the flexibility buys you, especially once you add the resolver batching layer GraphQL needs to perform well.
Is gRPC overkill for a small team?
For service-to-service calls inside your own infrastructure, no, it's often simpler than it sounds once the tooling is set up. For anything a browser or an external partner needs to call directly, it usually adds more friction than it's worth at small scale.
Can we use more than one protocol in the same system?
Yes, and most companies do once they have both internal services and external integrations. A common pattern is gRPC between internal services, REST or GraphQL at the edge facing customers, with a gateway translating between them.
Sources
Where we quote a benchmark, we show its source. Other figures in this guide are estimates or general guidance, so check them against your own numbers.
- Deployment frequency by DORA performance cluster (max days between deploys). DORA Accelerate State of DevOps 2024 (Google Cloud), cluster table via Octopus Deploy analysis, 2024.
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.
REST, GraphQL, or gRPC: Picking by Use Case, Not Trend
A decision guide comparing REST, GraphQL, and gRPC for internal services, public APIs, and mobile clients, and the tradeoffs each one hides.
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: 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.
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.