The Decision Framework
TL;DR
Default to REST. Switch to GraphQL if you have diverse clients with different data needs. Switch to gRPC for internal microservice communication where performance matters. Add real-time protocols only when you need server-push or bidirectional communication. In interviews, spend at most 5 minutes on this decision.
The Menu Problem
You're at a restaurant with a 47-page menu. Every cuisine, every dietary restriction, every possible side dish. You spend 20 minutes deciding, and the waiter is getting impatient.
That's what happens when engineers approach API protocol selection without a framework. There are too many options, too many blog posts arguing for their favorite, and too many edge cases to consider. You end up over-thinking a decision that, in most cases, has an obvious answer.
The goal of this lesson is to give you a decision flowchart — a fast, reliable way to pick the right protocol and move on with your design.

The Decision Flowchart
Here's the framework as a series of questions. Walk through them in order — the first "yes" gives you your answer.
Step 1: Do you need real-time, bidirectional communication?
Examples: Live chat, multiplayer gaming, collaborative editing (like Google Docs), live trading platforms.
If yes → Use WebSockets. They give you a persistent, full-duplex connection. Both client and server can send messages at any time.
If you only need server-to-client push (live dashboards, notification feeds, stock tickers) → Consider Server-Sent Events (SSE). It's simpler than WebSockets, works over plain HTTP, and reconnects automatically.
If neither → Move to Step 2.
Step 2: Is this internal service-to-service communication where performance is critical?
Examples: A recommendation service calling a feature store. A payment service calling a fraud detection service. A gateway routing to dozens of backend microservices.
If yes → Use gRPC with Protocol Buffers. You get binary serialization, HTTP/2 multiplexing, code generation, and streaming. The tight coupling (shared .proto files) is acceptable because you control both sides.
If no → Move to Step 3.
Step 3: Do you have multiple clients with significantly different data needs?
Examples: A mobile app that needs minimal data (limited bandwidth, small screens) AND a web dashboard that needs rich, nested data — both hitting the same backend. Or a platform with dozens of third-party integrators who each need different subsets of your data.
If yes → Use GraphQL. Let each client request exactly what it needs. One endpoint, infinite flexibility.
If no → Move to Step 4.
Step 4: Default to REST.
If you got here, REST is your answer. It's simple, well-understood, has incredible tooling, and works for the vast majority of use cases.
Don't feel bad about picking REST. It's not the "boring" choice — it's the correct choice for most systems. The entire internet runs on it.
Why REST Is the Default (Not Just the Fallback)
Some engineers treat REST as the "I couldn't think of anything better" option. That's backwards. REST is the default because it has the best trade-off profile for most situations:
| Factor | REST Advantage |
|---|---|
| Developer familiarity | Every engineer knows REST. Zero onboarding cost. |
| Tooling | Swagger/OpenAPI, Postman, curl, browser dev tools, CDNs — massive ecosystem. |
| Caching | HTTP caching headers work natively. CDNs cache GET requests automatically. |
| Debugging | Human-readable JSON. You can inspect requests in browser dev tools. |
| Statelessness | Each request is self-contained. Scales horizontally with no session affinity. |
| Standards | HTTP status codes, content negotiation, CORS — you get these for free. |
REST covers roughly 90% of API use cases. The other protocols exist for the other 10% — and knowing when to use them is what separates a senior engineer from a junior one.
Interview Tip
In a system design interview, say "I'll use REST for the API layer" and move on — unless the system has a specific characteristic that calls for something else. Don't spend more than a sentence on this unless the interviewer pushes back. Your time is better spent on data modeling, scaling, and trade-offs.
When GraphQL Actually Makes Sense
GraphQL is not "REST but better." It solves specific problems that REST doesn't handle well. Here are the signals that GraphQL might be the right choice:
Signal 1: Over-Fetching Is Measurable
Your mobile app calls GET /users/42 and gets back 30 fields, but only displays 3. You've measured this and it's wasting meaningful bandwidth — especially on slow mobile networks in emerging markets.
If you haven't measured it, you don't have this problem. Don't optimize for a pain you don't feel.
Signal 2: Under-Fetching Causes Waterfall Requests
To render one screen, your app makes 4-5 sequential REST calls:
1. GET /users/42
2. GET /users/42/posts
3. GET /posts/101/comments
4. GET /users/42/followers?limit=5
Each call waits for the previous one. On a 200ms round-trip connection, that's 800ms of pure network latency before rendering starts. GraphQL fetches all of this in one query.
Signal 3: Diverse Clients with Different Needs
A mobile app, a web dashboard, a TV app, and an API for third-party developers all hit the same backend. Each needs different data shapes. With REST, you end up with:
- /users/42?fields=name,avatar (mobile)
- /users/42?include=posts,followers,activity (web)
- /users/42/summary (TV)
- A versioned API for third parties
This endpoint proliferation is the exact problem GraphQL was invented to solve.
Signal 4: Rapid Frontend Iteration
Your frontend team ships new features weekly and constantly needs new data combinations. With REST, every new screen means asking the backend team for a new endpoint or query parameter. With GraphQL, the frontend team queries what they need from the existing schema — no backend changes required.
Interview Tip
If you choose GraphQL, name the specific signal that made you pick it. "We have mobile and web clients with very different data needs, so GraphQL lets each client request exactly what it needs" is a strong answer. "GraphQL is more modern" is a weak one.
When RPC/gRPC Makes Sense
gRPC is almost always the right choice for internal, backend-to-backend communication in a microservices architecture. Here are the signals:
Signal 1: You Control Both Sides
gRPC requires a shared .proto file between client and server. This tight coupling is fine when both services are in your organization. It's a problem when third-party developers need to integrate.
Signal 2: Performance Is Measurable
You've profiled your system and JSON serialization/deserialization is a meaningful bottleneck. Protocol Buffers' binary encoding is 3-10x smaller than equivalent JSON and 20-100x faster to parse, depending on the message structure.
Remember: this speed comes from binary serialization, not from "being faster than HTTP." gRPC uses HTTP/2. If you used REST with HTTP/2 and a binary format like BSON (Binary JSON) or MessagePack, you'd close much of the gap.
Signal 3: You Need Streaming
gRPC natively supports four communication patterns:
| Pattern | Description | Example |
|---|---|---|
| Unary | One request, one response | GetUser(id) → User |
| Server streaming | One request, stream of responses | WatchStockPrice(ticker) → stream of prices |
| Client streaming | Stream of requests, one response | UploadChunks(stream of bytes) → UploadResult |
| Bidirectional streaming | Stream in both directions | Chat(stream of messages) ↔ stream of messages |
If your use case needs streaming between backend services, gRPC handles it natively. REST makes you bolt on workarounds.
Signal 4: Polyglot Microservices
Your services are written in Go, Python, Java, and Rust. The .proto file generates type-safe client/server code in all of these languages. No hand-writing HTTP clients, no worrying about JSON field naming conventions across languages.
When to Reach for Real-Time Protocols
This is the simplest decision of the bunch:
| You need... | Use... | Why |
|---|---|---|
| Server pushing updates to the client | SSE (Server-Sent Events) | Simple, HTTP-based, auto-reconnects. Works for dashboards, notifications, live feeds. |
| Bidirectional real-time communication | WebSockets | Full-duplex over a persistent connection. Chat, gaming, collaborative editing. |
| Peer-to-peer media streaming | WebRTC | Direct browser-to-browser. Video calls, screen sharing. Your server is only for signaling. |
| Periodic updates, low frequency | REST with polling | Simple setInterval + GET. Don't over-engineer — if updates happen every 30 seconds, polling is fine. |
The key insight: Real-time protocols don't replace REST/GraphQL/gRPC. They work alongside them. A chat application still uses REST for loading message history and user profiles — WebSockets handle only the live message stream.
The Mixed-Protocol Pattern
In the real world, production systems almost always use multiple protocols. This isn't over-engineering — it's using the right tool for each job.
The most common pattern:
┌─────────────┐ REST/GraphQL ┌──────────────┐
│ Browser / │ ──────────────────→ │ API Gateway │
│ Mobile App │ ←── WebSockets ─── │ │
└─────────────┘ └──────┬───────┘
│
gRPC │ (internal)
│
┌────────────────┼────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ User │ │ Order │ │ Notif. │
│ Service │ │ Service │ │ Service │
└───────────┘ └───────────┘ └───────────┘
- REST or GraphQL for the public-facing API (clients, partners, third-party developers)
- gRPC for internal service-to-service communication (speed, type safety, streaming)
- WebSockets for real-time features (notifications, live updates)
This is what companies like Google, Netflix, and Uber actually do. In an interview, mentioning this pattern shows architectural maturity.
Interview Tip
If you say "REST for the public API, gRPC for internal services," the interviewer knows you understand real-world architecture. If you say "gRPC for everything," they'll wonder if you've considered browser clients and third-party integrators.
Interview Strategy: The 5-Minute Rule
Here's a practical truth: API protocol selection should take at most 5 minutes in a system design interview. It's an important decision, but it's not where you should spend your time. Here's the ideal flow:
- State your default (30 seconds): "I'll use REST for the client-facing API."
- Check for signals (1 minute): Does the system have real-time needs? Multiple diverse clients? Internal microservices? Performance-critical paths?
- Adjust if needed (1-2 minutes): "Since we have both a mobile app and a web dashboard with different data needs, I'll use GraphQL for the client-facing API. For the internal communication between the recommendation engine and the user service, I'll use gRPC since performance matters there."
- Sketch the key endpoints (2-3 minutes): Define 3-5 main endpoints/queries/methods. Don't exhaustively list every endpoint — just enough to show the contract.
- Move on. The interviewer wants to see that you can make a decision and justify it. They don't want a 15-minute lecture on REST vs GraphQL.
What Junior vs Senior Looks Like
| Level | What the interviewer expects |
|---|---|
| Junior | Pick REST. Define CRUD endpoints. Use correct HTTP methods and status codes. |
| Mid-level | Pick REST by default. Know when GraphQL or gRPC might be better. Define clean resource hierarchies. |
| Senior | Pick the right tool for each component. Justify trade-offs. Consider versioning, backward compatibility, and evolution. Mention the mixed-protocol pattern if appropriate. |
| Staff+ | All of the above, plus API governance, schema registries, backward compatibility strategies, and how API design affects team boundaries and organizational structure. |
The gap isn't knowing about GraphQL and gRPC. It's knowing when not to use them.
Frontend and Product Roles: Why API Design Matters More
If you're interviewing for a frontend, full-stack, or product engineering role, API design carries extra weight. You're the person who consumes the API. The interviewer wants to see that you can:
- Design APIs that your frontend actually needs. Don't just list backend CRUD endpoints — think about what the UI requires.
- Identify over-fetching and under-fetching. You live with these problems daily.
- Propose practical solutions. "We could add a
?fields=parameter" or "This is a good case for GraphQL because our mobile app needs a subset of what the web app shows." - Think about error states. What does the frontend show when the API returns a 404? A 500? A timeout?
For backend roles, API design is one piece of the puzzle. For frontend roles, it's often the central piece.
Common Interview Signals and What They Mean
Here's a cheat sheet for reading what the interviewer is actually probing when they ask about APIs:
| Interviewer says... | They're really asking... | Strong answer includes... |
|---|---|---|
| "How would the client and server communicate?" | "Do you know the basics of API design?" | State REST as default, define key endpoints with HTTP methods |
| "The mobile app is slow — too much data." | "Do you know about over-fetching?" | Mention field filtering (?fields=), or suggest GraphQL if the problem is systemic |
| "We have 50 microservices calling each other." | "Do you know about gRPC?" | Suggest gRPC for internal communication, explain why (binary serialization, code gen, streaming) |
| "How do users see updates in real time?" | "Do you know about push protocols?" | Distinguish between WebSockets (bidirectional) and SSE (server-push only), pick the right one |
| "What if we need to support a mobile app AND a web app AND a public API?" | "Can you architect for diverse clients?" | GraphQL or REST with BFF (Backend for Frontend) pattern. Explain the trade-off. |
| "How would you version this API?" | "Do you think about backward compatibility?" | URL versioning (/v2/users) vs header versioning, deprecation strategy |
| "Walk me through an API call end-to-end." | "Do you understand the full request lifecycle?" | Client → DNS → TLS → HTTP request → load balancer → API gateway → service → database → response |
Quick Recap
- Follow the flowchart: Real-time needed? → WebSockets/SSE. Internal services, performance-critical? → gRPC. Diverse clients, different data needs? → GraphQL. Everything else? → REST.
- REST is the default, not the fallback. It covers 90% of use cases with the best trade-off profile.
- GraphQL solves real problems — over-fetching, under-fetching, diverse clients — but adds complexity. Only reach for it when you feel the pain.
- gRPC is for internal communication. The speed comes from binary serialization (Protocol Buffers), not from avoiding HTTP. It literally uses HTTP/2.
- Mix protocols in production. REST for public, gRPC for internal, WebSockets for real-time. This is the industry norm.
- Spend at most 5 minutes on protocol selection in an interview. State your choice, justify it in one sentence, sketch key endpoints, and move on.
- The gap between junior and senior isn't knowing about exotic protocols — it's knowing when the simple choice is the right choice.
Interview Expectations: Junior vs. Senior
- Junior/Mid-level: Expected to match protocols to simple use cases (e.g., "I'd use WebSockets for chat"). Might default to REST for everything without considering alternatives.
- Senior/Staff: Drives the protocol decision based on the exact constraints of the clients and network. Proposes GraphQL when aggregating from multiple backend services for heterogeneous clients. Proposes gRPC for internal microservice communication due to strict contracts and low latency. Mentions fallback strategies for real-time (e.g., long-polling if WebSockets fail).