Thuan: OK Alex, last time you promised we’d talk about APIs. So here’s my question. I’ve been using REST for years. It works fine. Why do people keep telling me I should switch to GraphQL?
Alex: Because GraphQL solves a real problem. But first — do you actually have that problem?
Thuan: What do you mean?
Alex: Let me explain with our restaurant analogy. Think of APIs like ordering food. REST is like a fixed menu. Each dish has a number. You say, “I want number 7.” You get exactly what number 7 is. No more, no less.
Thuan: That sounds fine to me.
Alex: It is fine. Until you want something different. What if you want number 7, but without onions, with extra cheese, and can you add the sauce from number 12? With REST, you can’t customize like that. You get what’s on the menu. Period.
Thuan: So I’d need to make multiple requests? Like, first get the user, then get their orders, then get the product details for each order?
Alex: Exactly. That’s called over-fetching and under-fetching. Over-fetching means: “I asked for the user, and I got their name, email, address, profile picture, preferences, and 30 other fields. I only needed the name.” Under-fetching means: “I asked for the user but I also need their orders, and now I need a second request.”
GraphQL: The Custom Order Kitchen
Thuan: So how does GraphQL fix this?
Alex: GraphQL is like a restaurant where you write your own order. You say, “I want the user’s name and email, plus their last three orders, and for each order, just the total and the product name.” And the kitchen gives you exactly that. One request, exactly the data you need.
Thuan: That sounds amazing. Why doesn’t everyone use it?
Alex: Because running a “write your own order” kitchen is harder than running a fixed menu. Think about it. With a fixed menu, the chef knows exactly what to prepare. He can pre-cook things, organize the kitchen around specific dishes. With custom orders, every request is different. The kitchen needs to be more flexible, which means more complex.
Thuan: What does “more complex” mean in practice?
Alex: A few things. First, performance can be tricky. When someone writes a deep query — “give me all users, with all their orders, with all the products in each order, with all the reviews for each product” — that can trigger hundreds of database queries behind the scenes. It’s called the N+1 problem. You asked for one thing, but under the hood, the server is making N additional queries.
Thuan: How do you solve that?
Alex: DataLoader. It’s a pattern where you batch and cache database requests. Instead of querying the database 100 times for 100 products, you query once with all 100 product IDs. But you have to build this yourself. REST doesn’t have this problem because each endpoint is designed to return a specific, optimized query.
Thuan: What other downsides does GraphQL have?
Alex: Caching is harder. With REST, each URL is a unique resource. You can cache easily — your browser, CDN, and proxy servers all understand URLs. With GraphQL, every request is a POST to the same endpoint. The URL is always the same. Traditional caching doesn’t work. You need special tools like Apollo Client or Relay to handle caching on the client side.
gRPC: The Intercom Between Kitchens
Thuan: OK, I get REST and GraphQL. But where does gRPC fit in?
Alex: gRPC is different. It’s not really for the front door of your restaurant — the place where customers order. It’s for the intercom between kitchens. Remember our microservices conversation? When services talk to each other, they need to be fast, efficient, and precise.
Thuan: So gRPC is for service-to-service communication?
Alex: Primarily, yes. Here’s why. gRPC uses Protocol Buffers — a binary format. Instead of sending data as JSON text that humans can read, it sends compact binary data. It’s like the difference between sending a handwritten letter and sending a telegram with codes. The telegram is smaller and faster, but harder for humans to read.
Thuan: How much faster are we talking?
Alex: Roughly 2 to 10 times faster than REST with JSON, depending on the data. And that matters when services are calling each other thousands of times per second. A few milliseconds saved per call adds up.
Thuan: But you said it’s not great for frontend use?
Alex: Not traditionally. Browsers don’t natively support gRPC because it requires HTTP/2 and binary framing. There are workarounds — gRPC-Web, for example — but they add complexity. For browser-to-server communication, REST or GraphQL is usually simpler.
The Waiter Analogy: All Three Side by Side
Thuan: Can you compare all three in one analogy? I want a mental picture.
Alex: Sure. Think of it this way:
REST is a traditional waiter with a fixed menu. You point to item number 7. The waiter brings it. Simple, predictable, everyone knows how it works. Most restaurants — most apps — work perfectly fine like this.
GraphQL is a waiter who takes custom orders. You describe exactly what you want. “I want the chicken from the lunch menu, the sauce from the dinner menu, half portion, extra vegetables.” The waiter writes it all down and brings exactly that. Powerful, but the kitchen needs to be more sophisticated.
gRPC is the intercom system between the kitchen and the prep station. It’s fast, coded, efficient. The head chef doesn’t say, “Please prepare two portions of diced onions.” She presses a button that means “2-DICE-ONION.” The prep station understands instantly. Faster than talking, but only works between people who share the same code book.
Thuan: I love that. So REST for most APIs, GraphQL for complex client needs, gRPC for service-to-service.
Alex: That’s the simple version, and it’s right 90% of the time.
When to Choose Each One — A Practical Guide
Thuan: Let’s get specific. When do I choose REST?
Alex: Choose REST when:
Your API is simple and resource-based. Users, products, orders — things you can identify with a URL. Your client applications have predictable data needs. You want to leverage HTTP caching. Your team already knows REST. And honestly — for most web applications, REST is the right choice. Don’t overthink it.
Thuan: When do I choose GraphQL?
Alex: Choose GraphQL when:
You have multiple client applications — web, mobile, tablet — and each one needs different data. Mobile needs less data because of bandwidth. Desktop needs more because it has more screen space. Instead of building three versions of every REST endpoint, you build one GraphQL API and let each client request what it needs.
Also choose GraphQL when your data is highly connected. Social networks are the classic example. User has friends, friends have posts, posts have comments, comments have authors. With REST, you’d chase your tail with nested requests. With GraphQL, one query can walk the entire graph.
Thuan: And gRPC?
Alex: Choose gRPC when:
You have microservices talking to each other and performance matters. Financial trading systems, real-time gaming backends, IoT data pipelines. Also when you need streaming. gRPC supports bidirectional streaming natively. Both client and server can send data to each other at the same time. That’s hard with REST and GraphQL.
And when you need strong contracts. Protocol Buffers define exactly what the request and response look like. If someone changes the format, the code won’t compile. That’s a safety net that JSON doesn’t give you.
Common Mistakes I’ve Seen
Thuan: What are the biggest mistakes teams make when choosing an API style?
Alex: Three big ones.
Mistake 1: Using GraphQL for a simple CRUD app. If your app is “create, read, update, delete” for five resources, GraphQL is overkill. You’re adding complexity for no benefit. REST handles CRUD beautifully. That’s literally what it was designed for.
Thuan: I’ve seen this. Teams add GraphQL and then every query is basically the same as a REST endpoint. They just moved the complexity to a different place.
Alex: Mistake 2: Not versioning your REST API. APIs change. Your version 1 might return user data as {name: "Alex"}. Version 2 might change it to {firstName: "Alex", lastName: "Smith"}. If you don’t version your API, you break every client that depends on the old format. Always version. /api/v1/users, /api/v2/users.
Thuan: What about the third mistake?
Alex: Mistake 3: Exposing your microservices directly to the frontend. This is common when teams adopt microservices. They let the frontend call ten different services. Now the frontend needs to know about service discovery, handle failures for each service, and aggregate data from multiple sources. That’s a mess.
Thuan: So what’s the fix?
Alex: Use an API Gateway. It’s like a receptionist at the front of the restaurant. The customer talks to the receptionist. The receptionist knows which kitchen stations to call. The customer doesn’t need to know how the kitchen is organized. The gateway handles routing, authentication, rate limiting, and response aggregation.
Key Takeaways You Can Explain to Anyone
Thuan: Wrap-up time. Three lines or less.
Alex:
-
REST is the default. Use it unless you have a specific reason not to. It’s simple, well-understood, and cacheable.
-
GraphQL shines when clients need flexibility. Multiple clients, complex data relationships, or when over-fetching is a real performance problem.
-
gRPC is for machines talking to machines. Fast, efficient, strongly typed. Not for browsers, not for simple APIs.
-
You can mix them. Use GraphQL for your frontend API, gRPC between your microservices, and REST for your public developer API. They’re not mutually exclusive.
Thuan: That fourth point is key. It’s not “pick one.” It’s “pick the right one for each situation.”
Alex: Exactly. The best API architecture is often a combination. And that’s totally fine.
Thuan: Same time next week? I want to understand how Netflix handles 200 million users without everything falling over.
Alex: System design! My favorite topic. Bring extra coffee — that one’s going to be a longer conversation.
This is Part 2 of the Tech Coffee Break series — casual conversations about real tech concepts, designed for listening and learning.
Next up: Part 3 — How Does Netflix Handle 200 Million Users?