Chapter 11 — API Design (REST vs gRPC vs GraphQL)

Chapter 11 — API Design (REST vs gRPC vs GraphQL)

Hey everyone! Welcome back to Namaste System Design! 🙏

An API is the menu of a service — it defines what you can order and how. When components talk to each other, they talk through APIs. Get the API design right and everything downstream is pleasant; get it wrong and every client suffers. Today we compare the three heavyweights: REST, gRPC, and GraphQL.

What we will cover:

  • What an API contract is (the menu analogy)
  • REST — the web's default
  • GraphQL — ask for exactly what you need
  • gRPC — blazing-fast service-to-service
  • Over-fetching vs under-fetching
  • A clean decision table
  • Interview Questions

1. The Menu Analogy

┌─────────────────────────────────────────────────────────────┐
│   An API is a CONTRACT — a menu that says:                  │
│   "Here's what you can ask for, and here's the format       │
│    of what you'll get back."                                │
│                                                             │
│   The client (customer) orders; the server (kitchen)        │
│   fulfills. Neither needs to know the other's internals.    │
└─────────────────────────────────────────────────────────────┘

2. REST — The Web's Default

REST models everything as resources (nouns) accessed via HTTP verbs. It's simple, universal, and cache-friendly.

   GET    /users/1          → fetch user 1
   POST   /users            → create a user
   PUT    /users/1          → update user 1
   DELETE /users/1          → delete user 1

   HTTP verbs = actions.  URLs = resources.  JSON = data.

The pain of REST — over/under-fetching:

   You want just a user's NAME. But GET /users/1 returns the
   whole object (name, email, address, orders...).
   → OVER-FETCHING (got too much data). 📦📦📦

   You want a user AND their posts AND their comments.
   → 3 separate calls: /users/1, /users/1/posts, /posts/x/comments
   → UNDER-FETCHING (too many round trips). 🔁🔁🔁

3. GraphQL — Ask for Exactly What You Need

GraphQL (from Facebook) fixes over/under-fetching. There's one endpoint, and the client sends a query describing precisely the fields it wants.

   Query:                          Response (exactly that shape):
   {                               {
     user(id: 1) {                   "user": {
       name                            "name": "Aisha",
       posts { title }                 "posts": [{ "title": "..." }]
     }                               }
   }                               }

   ONE request. EXACTLY the fields asked for. No waste. ✅

Trade-offs: flexible and great for complex frontends (and mobile, where bandwidth matters), but harder to cache (it's usually POST to one URL), and a badly-written query can be very expensive on the server.


4. gRPC — Speed Between Services

gRPC (from Google) is built for service-to-service communication inside your backend, where speed matters more than human-readability.

   REST sends JSON (text)  → human-readable but bulky/slow
   gRPC sends Protobuf (binary) → tiny, super fast to parse ⚡

   + runs over HTTP/2 (multiplexing, streaming)
   + strongly typed contract (.proto file)
   + great for microservices talking to each other
   − not browser-friendly, binary is hard to debug by eye
   Microservice A ──gRPC (binary, fast)──▶ Microservice B
   Browser        ──REST/GraphQL (JSON)──▶ Public API

   Rule of thumb: gRPC INSIDE the datacenter,
                  REST/GraphQL at the PUBLIC edge.

5. The Decision Table

RESTGraphQLgRPC
Data formatJSON (text)JSON (text)Protobuf (binary)
EndpointsMany (per resource)OnePer service method
FetchingFixed shape (over/under)Exactly what you askFixed, typed
SpeedGoodGoodFastest
CachingEasy (HTTP caching)HarderHarder
Best forPublic APIs, CRUD, simplicityComplex/flexible frontends, mobileInternal microservices

Interview-safe default: "I'd start with REST for a public API because it's simple and cache-friendly; use GraphQL if clients need flexible, nested data; and gRPC for high-performance internal service-to-service calls."


6. Good API Design Principles (Any Style)

✔ Use clear nouns for resources: /orders, not /getOrders
✔ Use proper HTTP status codes: 200 OK, 201 Created, 404, 500
✔ VERSION your API: /v1/users → so you can change without
  breaking old clients
✔ PAGINATE big lists: never return 1,000,000 rows at once
✔ Be consistent: same naming, same error format everywhere
✔ Secure it: auth tokens, rate limiting (Chapter 13)

Interview Questions — Quick Fire!

Q: What is REST?

"REST is an architectural style where everything is modeled as a resource identified by a URL, and you act on it using HTTP verbs — GET to read, POST to create, PUT to update, DELETE to remove — typically exchanging JSON. It's simple, stateless, and cache-friendly, which is why it's the default for public web APIs."

Q: What problem does GraphQL solve?

"It solves over-fetching and under-fetching. With REST, an endpoint returns a fixed shape, so you often get more data than you need or have to make several calls to assemble what you want. GraphQL exposes one endpoint where the client specifies exactly which fields it needs, so it gets precisely that in a single request — great for complex frontends and bandwidth-limited mobile clients."

Q: When would you use gRPC over REST?

"For internal service-to-service communication where performance matters. gRPC uses binary Protobuf over HTTP/2, which is much faster and smaller than JSON, supports streaming, and enforces a strongly typed contract. The downside is it's not browser-friendly and harder to debug by eye, so I'd use gRPC inside the datacenter between microservices and REST or GraphQL at the public edge."

Q: Why is API versioning important?

"Because clients depend on the API's shape. If you change it without versioning, you break every existing client. Versioning — like putting /v1/ in the path — lets you evolve the API by releasing /v2/ while old clients keep using /v1/ until they migrate, avoiding breaking changes."


Key Points to Remember

ConceptKey Takeaway
RESTResources + HTTP verbs + JSON. Simple, cache-friendly; suffers over/under-fetching.
GraphQLOne endpoint, client asks for exact fields. Flexible; harder to cache.
gRPCBinary Protobuf over HTTP/2. Fastest; best for internal microservices.
DefaultREST public + gRPC internal; GraphQL when clients need flexible nested data.
Good designClear nouns, status codes, versioning, pagination, consistency, security.

What's Next?

Chapter 12 covers how we serve content fast to the whole planet: the CDN. How does a user in Tokyo get a video as quickly as a user in New York? By keeping copies close to everyone.

Keep designing, keep scaling! See you in the next one!