GraphQL & gRPC
The two common answers to "REST is not the right shape here" — and what each one costs.
When REST Stops Fitting
| REST | GraphQL | gRPC | |
|---|---|---|---|
| Shape | Resources | One typed graph | Typed procedure calls |
| Wire format | JSON | JSON | Binary protobuf |
| Best for | Public APIs | Varied client needs | Internal service-to-service |
| Browser support | Native | Native | Needs a proxy |
| Caching | HTTP, for free | Application-level work | Application-level work |
GraphQL
GraphQL exposes one endpoint and a typed schema. The client states exactly what it wants and receives that shape — which ends both over-fetching and the round-trip chains REST clients build.
type Query { order(id: ID!): Order }
type Order {
id: ID!
total: Int!
customer: Customer! # the client decides whether to fetch this
lines: [OrderLine!]!
}
# one request, exactly the fields this screen needs
query { order(id: "42") { total customer { name } } }
| Buys | Costs |
|---|---|
| No over- or under-fetching | HTTP caching no longer applies |
| One request for a whole screen | Query cost is now your problem |
| A strongly typed, introspectable schema | Real server-side complexity |
| Clients evolve without server changes | Errors arrive inside a 200 |
A public GraphQL endpoint also needs depth and cost limits. Nothing stops a client requesting friends-of-friends-of-friends and asking your database to do a week of work in one request.
gRPC
gRPC is remote procedure calls over HTTP/2 with protocol buffers: you define the service and messages in a .proto file, generate typed client and server code for every language you use, and send compact binary frames.
syntax = "proto3";
service Orders {
rpc GetOrder (GetOrderRequest) returns (Order);
rpc WatchOrders (WatchRequest) returns (stream Order); // server streaming
}
message GetOrderRequest { string id = 1; }
message Order {
string id = 1; // field numbers are the wire contract —
int64 total = 2; // never reuse or renumber them
string customer = 3;
}
| Strength | Cost |
|---|---|
| Compact and fast — binary, multiplexed | Not human-readable; needs tooling to debug |
| Generated clients in every language | A build step and a shared proto repository |
| Streaming in both directions | Browsers need grpc-web and a proxy |
| Schema-first by construction | Field numbering discipline forever |
Choosing Between Them
| Situation | Reach for |
|---|---|
| A public API for third parties | REST — everyone can call it with curl |
| Many clients wanting different slices | GraphQL |
| Mobile on a poor connection | GraphQL — one round trip, minimal payload |
| Internal services, high volume | gRPC |
| Streaming updates between services | gRPC |
| Anything a browser calls directly | REST or GraphQL |
Mixing them is normal and often correct: REST at the public edge, gRPC between internal services, GraphQL in a gateway that fans out to both. The failure is adopting one because it is fashionable and inheriting problems the previous shape did not have.
Interview Questions
What does GraphQL solve that REST does not?
Over- and under-fetching. One request returns exactly the fields a screen needs, instead of several round trips or a fixed payload with unused data.
What is the N+1 problem in GraphQL?
A list resolver runs a nested resolver once per item, issuing one query each. Batching with a DataLoader — collecting ids within a tick and fetching them together — is the standard fix.
What does GraphQL cost you?
HTTP caching stops applying, query cost becomes your responsibility, errors arrive inside 200 responses, and the server gets substantially more complex.
Why is gRPC faster than REST over JSON?
Binary protobuf payloads are much smaller than JSON, and HTTP/2 multiplexes many calls over one connection with header compression.
Why do protobuf field numbers matter?
They are the wire contract. Renaming a field is safe; reusing a retired number makes old data decode as something else entirely, so retired numbers are reserved permanently.
When would you not use gRPC?
For anything a browser calls directly — it needs grpc-web and a proxy — and for public APIs, where third parties expect to call you with ordinary HTTP tools.