Trade-offs · Foundations
REST vs gRPC vs GraphQL
Which API style to pick for browsers, partners and your own services, with call counts, message sizes and delay worked out.
Asked at: SDE-1SDE-2Senior
The decision
An API is how one program calls another. In REST, each thing has a URL, and HTTP methods such as GET and POST say what to do. In GraphQL, the caller sends one query that names the exact fields it wants. In gRPC, a caller runs a function on another server. The two sides share a contract file, and messages travel in a small binary format. The choice depends on who calls you and how many calls a screen needs.
Choose REST when
- Browsers, partners or the public call your API. Everyone can call it and test it with simple tools.
- The work is simple create, read, update and delete.
- You want HTTP caches to work by URL.
Choose gRPC when
- Your own services call each other, and you control both sides.
- You want a strict contract in a
.protofile, with generated code in each language. - You need streaming, where one call carries many messages.
- Call volume is high and each millisecond counts.
Choose GraphQL when
- Many screens need different slices of data from many resources, and the app makes too many calls.
- Mobile users are on slow networks, where a round trip costs 100 ms or more.
- The front-end team changes screens often and should not wait for new endpoints.
The numbers that change the answer
Worked example 1 (Assumption: an order screen). One round trip from phone to server takes 100 ms. The server needs 20 ms per call. The screen needs an order, its customer, and 3 items. The phone learns the customer id and item ids only from the order.
- REST: 1 + 1 + 3 = 5 calls. One after another: 5 x (100 + 20) = 600 ms. Best case, with the last 4 calls sent together: 2 x 120 = 240 ms.
- GraphQL: one call. Assumption: the server gets all the data in 40 ms. Time = 100 + 40 = 140 ms, which is 100 ms less than the best REST case.
Worked example 2 (Assumption: our own services). 8,000 user requests arrive per second, and each causes 4 calls. That is 32,000 calls per second. The message is an order with an order id (1048576), a customer id (20481), a total (45000) and 3 items. Each item has an item id and a quantity.
- JSON, written without spaces: 136 bytes (counted with a script).
- Protobuf: 33 bytes. A number takes a 1-byte tag plus a varint, which stores 7 bits of the number in each byte. The three order numbers take 4 bytes each: 12. Each item takes 2 bytes of tag and length, 3 for the item id and 2 for the quantity: 7. Three items take 21. Total = 12 + 21 = 33. Field names are not sent.
- JSON traffic = 32,000 x 136 = 4,352,000 bytes per second, about 4.35 MB per second. Protobuf = 32,000 x 33 = 1,056,000 bytes per second, about 1.06 MB per second.
- Assumption: a 1 gigabit link carries 1,000 / 8 = 125 MB per second. JSON uses 4.35 / 125 = 3.5% of it. Protobuf uses 1.06 / 125 = 0.85%. We count message bodies only.
- So the network is not the reason to pick gRPC. Assumption: each call takes 15 ms, and gRPC saves 5 ms per call. Four calls in a row save 20 ms. Removing 2 of the 4 calls saves 2 x 15 = 30 ms.
What breaks with each choice
- REST: over-fetching (extra fields) and under-fetching (more calls). Fix: add a combined endpoint for the heavy screen, or a GraphQL layer in front.
- gRPC: browsers cannot make a normal gRPC call. gRPC-web needs a proxy and supports only normal calls and server streaming (see Sources). The messages are binary, so you cannot read them by eye. Fix: REST at the edge and gRPC inside.
- GraphQL: one query can be very expensive. A query for 20 orders and each customer can become 1 + 20 = 21 lookups, unless the server batches them into 2. HTTP caches by URL also work poorly, because most queries are POST requests to one URL. Fix: limit query depth and size, batch the lookups, and watch the cost of each query.
What it costs
- REST costs nothing extra.
- gRPC needs
.protofiles, code generation and extra tools for testing. Assumption: 2 engineer-weeks to set up for a team. - GraphQL needs a schema, limits, batching and monitoring. Assumption: 4 to 6 engineer-weeks for a first service.
- Switching later is easiest at the edge. You can add GraphQL in front of REST services without changing them. Inside, you move to gRPC one service at a time.
How each level answers
SDE-1: REST uses URLs and HTTP methods. GraphQL lets the caller choose the fields. gRPC calls a function on another server with a contract file.
SDE-2: I use REST for partners and browsers, because everyone can call it. I use gRPC between my own services for the contract and the generated code. I add GraphQL only if screens make too many calls.
Senior: The order screen costs 5 REST calls: 240 ms at best and 600 ms one by one, against 140 ms for GraphQL. Between services, Protobuf cuts 136 bytes to 33, but JSON uses only 3.5% of the link. So I choose gRPC for the contract, not for bandwidth. The failure with GraphQL is an expensive query, so I set depth and size limits. The fallback is a plain REST endpoint for that screen.
Staff: An API is a long promise to other teams. I choose the style that callers can use today: REST at the edge, gRPC inside, GraphQL only when screens show a measured call problem. An API platform team owns schema review. I run a new style beside the old one on the hottest path and do not rewrite what works. I measure calls per screen, p95 (the time within which 95 of 100 requests finish) screen load time and breaking-change incidents.
Say it in the interview
"For partners and browsers I use REST with JSON, and between my own services I use gRPC for the strict contract. Bandwidth is not the reason, because JSON would use only 3.5% of a 1 gigabit link at 32,000 calls per second. If the order screen needs 5 REST calls, about 240 ms at best, I add GraphQL for that screen, with query limits."
Common mistakes
- Choosing gRPC for speed without counting calls. Removing 2 of 4 calls saves more than a faster protocol.
- Using GraphQL for a simple partner API. Partners want a stable URL they can test, and you must now defend against expensive queries.
- Saying "REST is slow". The cost is the number of round trips, not the style.
Sources
- gRPC (
.protocontract, generated code, streaming): https://grpc.io/docs/what-is-grpc/introduction/ (opens in a new tab) (checked 26 Oct 2026). - gRPC-web (needs a proxy; unary and server streaming only): https://github.com/grpc/grpc-web (opens in a new tab) (checked 26 Oct 2026).
- Protobuf encoding (field number and type tag, 7 bits per byte, field names not sent): https://protobuf.dev/programming-guides/encoding/ (opens in a new tab) (checked 26 Oct 2026).
- GraphQL (exact fields, many resources in one request, type system): https://graphql.org/learn/ (opens in a new tab) (checked 26 Oct 2026).
- All timings, call counts, link speed and effort are assumptions made for teaching. The 136-byte and 33-byte sizes are calculated for the example order, using the Protobuf rules in the source above.
Understand the trade-off. Practise explaining your choice.
In an AI mock interview, the interviewer can push on a choice like this one: it changes a number and asks if your answer still holds.