REST vs gRPC vs GraphQL

Basics

Visual Representation

Rendering diagram...

What is it?

🍽️ Think of it like three different restaurant styles:

REST is like a fixed menu restaurant — the kitchen decides what's on each plate. You order "Plate #3" and you get whatever's on it, even if you only wanted the rice.

GraphQL is like a build-your-own-bowl place — you specify exactly what ingredients you want. "I want rice, chicken, no salad, extra sauce." You get EXACTLY what you asked for, nothing more.

gRPC is like a kitchen with a walkie-talkie to another kitchen — they communicate super fast in their own internal code language, not meant for customers. Optimized for machines talking to machines.

All three are ways to design APIs (Application Programming Interfaces) — the "menu" that your server offers to clients. They define HOW clients can ask for data and HOW the server responds.

💡 Simple Summary: REST = standard, resource-based. GraphQL = client picks exactly what it wants. gRPC = fast binary communication between services.

How it works — Like you're watching it happen

REST (Representational State Transfer):

  • Everything is a "resource" — Users, posts, comments are all resources with URLs: /users/123, /posts/456
  • HTTP methods as actions — GET /users (list all), GET /users/123 (get one), POST /users (create), PUT /users/123 (update), DELETE /users/123 (remove)
  • Server decides the response shape — You get the full user object whether you needed all fields or not.
  • Stateless — Each request is independent. No memory between calls.
  • GraphQL:

  • Single endpoint — Just POST /graphql for EVERYTHING.
  • Client writes a query — "Give me user 123's name and their last 3 posts' titles." The client describes EXACTLY what shape of data it wants.
  • Server resolves it — Fetches only the requested fields, joins the data, returns precisely what was asked.
  • No over-fetching or under-fetching — You get exactly what you need in ONE request.
  • gRPC (Google Remote Procedure Call):

  • Define a contract — Write a .proto file that defines available functions and data shapes (like a strict menu written in advance).
  • Code generation — Tools auto-generate client and server code from the .proto file. Type-safe, no guessing.
  • Binary format (Protocol Buffers) — Data sent as compact binary, not human-readable JSON. Much smaller and faster.
  • HTTP/2 under the hood — Supports streaming, multiplexing, all the HTTP/2 goodies.
  • But wait — if GraphQL is so flexible, why doesn't everyone use it?

    GraphQL adds COMPLEXITY: the server must handle arbitrary queries (some might be expensive), caching is harder (no URL-based caching like REST), and you need query complexity analysis to prevent abuse. REST is simpler, well-understood, and perfectly fine for most CRUD apps. Use GraphQL when you have many different clients (mobile, web, watch) each needing different data shapes from the same API.

    Why should you care? (Interview perspective)

  • 🎯 "Which API style would you choose for this system?" is asked in EVERY system design interview
  • Understanding trade-offs shows architectural maturity
  • Knowing when to mix them (REST externally, gRPC internally) is a senior engineer answer
  • Mobile-first design often benefits from GraphQL — mentioning this scores points
  • Key Things to Remember

  • REST is resource-oriented — URLs represent nouns (/users, /orders), methods represent verbs (GET, POST, PUT, DELETE).
  • GraphQL solves over/under-fetching — Mobile app needs just user name? Query exactly that. Web dashboard needs everything? Query all fields. One endpoint adapts.
  • gRPC is for service-to-service — Not for browsers (browsers can't easily speak gRPC). Perfect for microservices talking to each other internally.
  • Protocol Buffers — gRPC's data format. Binary (not human-readable), strongly typed, 3-10x smaller than JSON, backward-compatible with schema evolution.
  • REST versioning — /api/v1/users, /api/v2/users. GraphQL doesn't need versioning — you add fields without breaking old queries.
  • N+1 problem in GraphQL — Naive implementation: query 50 posts, then 50 separate DB calls for each post's author. Solved with DataLoader (batching).
  • Streaming with gRPC — Supports server streaming (one request, many responses), client streaming, and bidirectional streaming. REST can't do this natively.
  • Caching — REST is easiest to cache (URL = cache key). GraphQL caching is complex (POST requests, dynamic queries). gRPC caching is application-level.
  • Error handling — REST uses HTTP status codes (404, 500). GraphQL always returns 200 with errors in the response body. gRPC has its own status codes.
  • Best combo — Public API: REST (simple, cacheable). Mobile app: GraphQL (flexible queries). Internal services: gRPC (fast, type-safe).
  • Real Examples You Use Daily

    📱 Instagram/Facebook — Uses GraphQL (they invented it!). The mobile app queries exactly the fields it needs for the feed: post image URL, like count, first 3 comments, author name. The web app queries more fields (full comment list, shares, etc.) — same API, different queries.

    🚗 Uber internal services — Microservices (pricing, matching, maps, payments) communicate via gRPC. Binary format means faster serialization, strict contracts prevent breaking changes between teams.

    🌐 Twitter/X API — Public developer API is REST. GET /2/tweets/:id returns tweet data. Simple, well-documented, cacheable. Millions of third-party apps use it.

    🛒 Shopify — Offers both REST and GraphQL APIs. REST for simple integrations (get products, create orders). GraphQL for complex storefronts needing custom data shapes.

    Common Mistakes in Interviews

    Saying "GraphQL is better than REST" — Neither is universally better. They solve different problems. REST is simpler for CRUD, GraphQL for complex data needs. Always justify your choice based on the use case.

    Forgetting gRPC's limitations — gRPC doesn't work in browsers natively (need grpc-web proxy), isn't human-readable (can't test with curl easily), and requires schema management. It's not for public-facing APIs.

    Not mentioning the N+1 problem with GraphQL — If you suggest GraphQL without addressing this, you're showing you haven't used it in practice. Always mention DataLoader or query planning.

    Using REST for internal microservices — JSON serialization/deserialization is slow at scale. For internal service-to-service communication with known contracts, gRPC's binary Protobuf is 5-10x faster.

    Proposing one style for everything — The mature answer is: "REST for our public API because it's simple and cacheable, GraphQL for our mobile BFF (Backend For Frontend) to reduce over-fetching, and gRPC between internal microservices for speed and type safety."

    🎯 Interview One-Liner

    "I'd use REST for public APIs due to simplicity and cacheability, GraphQL for client-facing apps where different platforms need flexible data shapes, and gRPC for internal service-to-service communication where binary performance and strong typing matter — often combining all three in a single architecture."

    Interview Q&A

    Q: When would you choose GraphQL over REST?

    When I have multiple client types (mobile, web, watch) each needing different data from the same backend. Instead of building separate REST endpoints for each or over-fetching, GraphQL lets each client query exactly what it needs. Also when the data is highly interconnected (social graphs) and clients need to traverse relationships in different ways.

    Q: What's the over-fetching problem in REST?

    GET /users/123 returns ALL 30 fields (name, email, address, bio, avatar, settings...) even if the mobile app only needs name and avatar for a comment section. That's wasted bandwidth and parsing time — especially painful on slow mobile networks. GraphQL solves this: query { user(id:123) { name, avatar } } returns ONLY those two fields.

    Q: Why would you use gRPC between microservices?

    Speed and safety. Protocol Buffers (binary) are 5-10x smaller and faster to serialize than JSON. The .proto contract file ensures both services agree on the data shape at compile time — no runtime surprises. Plus gRPC supports streaming (useful for real-time data between services) and has built-in deadlines/cancellation. The trade-off is complexity and harder debugging (binary isn't human-readable).

    Q: How does GraphQL handle errors differently from REST?

    REST uses HTTP status codes: 404 means not found, 500 means server error. GraphQL ALWAYS returns HTTP 200 (even on errors!) with an "errors" array in the JSON body. Why? Because a GraphQL request might partially succeed — you asked for user name AND posts, the name resolved but posts failed. You get partial data + errors. This is by design but makes monitoring harder (you can't just alert on non-200 responses).

    Q: How do you prevent malicious/expensive GraphQL queries?

    (1) Query depth limiting — reject queries nested more than N levels deep. (2) Query complexity analysis — assign "cost" to each field, reject queries exceeding a budget. (3) Rate limiting per-user. (4) Persisted queries — in production, clients can only send pre-approved query IDs, not arbitrary query strings. This prevents "query { users { posts { comments { author { posts { comments... } } } } } }" attacks.

    Q: Explain Protocol Buffers (Protobuf) and why gRPC uses them.

    Protobuf is a binary serialization format created by Google. You define your data structure in a .proto file (like a schema), then tools generate code in any language. The binary format is 3-10x smaller than JSON, 20-100x faster to serialize/deserialize, and strongly typed. gRPC uses it because internal services care about speed and correctness more than human-readability. The .proto file also serves as living documentation of the API contract.

    Q: Can you use all three in one system?

    Absolutely — and many companies do! Public developer API: REST (simple, cacheable, well-understood by third parties). Mobile app gateway: GraphQL BFF (Backend For Frontend) that aggregates data from internal services into exactly what each screen needs. Between internal microservices: gRPC (fast binary communication with strict contracts). The GraphQL BFF calls internal gRPC services and shapes the response for the client.

    Quick Quiz

    1/5

    Instagram's mobile app needs only post image URL and like count for the feed. The server has 30 fields per post. Which API style avoids wasting bandwidth?