Resources, a graph, or procedures
REST puts nouns at URLs and leans on HTTP. GraphQL serves one typed graph; the client names its fields. gRPC calls typed procedures from a .proto file, over HTTP/2.
REST makes the phone wait twice
The order holds only restaurant and rider ids, so a second trip follows. GraphQL or a BFF fans out inside the data centre instead, at ≈1 ms a hop.
21
backend calls for one 20-order history screen
Each order’s restaurant resolves separately: 1 + 20. A per-request DataLoader collects one tick’s keys, drops duplicates and sends one batch: 2 calls.
Did it work?
Bad: “It’s a 200, so yes”
GraphQL errors usually ride in a 200; gRPC’s status arrives in trailers.
Good: Count errors, not 5xx
Alert on the errors list and gRPC codes, or dashboards stay green.
The BFF gives the screen 800 ms. Two hops down, Pricing hangs on a slow lock.
Deadlines travel
Each hop forwards the time left: 750 ms, then 600. When it runs out, every hop stops together.
Where gRPC hurts
- Browsers can’t speak it; gRPC-Web needs a translating proxy
- An L4 balancer pins each long-lived connection to one backend
- Partners expect HTTP and JSON they can read
Split by audience, not by service
Partners get versioned REST with OpenAPI. Apps get GraphQL or a BFF. Inside, services talk gRPC, and webhooks push events back out.
Remember
Choose per audience. Partners get REST with OpenAPI; apps get GraphQL or a BFF, one trip per screen; services talk gRPC with deadlines. Mixing all three is normal.