After this lesson, you will be able to: Compare GraphQL and gRPC to REST: what each is, when each is better, when each is worse, and the tradeoffs.
GraphQL and gRPC are the two main REST alternatives. Knowing the tradeoffs of all three makes you sound senior in interviews and helps you pick the right tool for a given problem.
A query language for your API + a runtime. Created at Facebook (2012, open-sourced 2015). Single endpoint (`/graphql`). Clients send a query specifying EXACTLY which fields they want. Server returns just those. Strongly typed schema (SDL, Schema Definition Language). Big ecosystem: Apollo, Relay, urql on clients; Apollo Server, Hot Chocolate, graphql-yoga on servers.
Compare to REST.
# Query (sent by client)query {user(id: 42) {nameposts(limit: 5) {titlecreatedAt}}}# Response{"data": {"user": {"name": "Alex","posts": [{ "title": "Hello", "createdAt": "..." }]}}}# REST equivalent: GET /users/42 + GET /users/42/posts?limit=5# = 2 requests, more data than needed, client must combine.
Mobile clients (bandwidth matters; under-fetching + over-fetching are real costs). Complex nested data with varying client needs (one screen wants a + b; another wants a + c). Backend-for-Frontend (BFF) layer that wraps many microservices. Frontend teams that move fast + don't want to coordinate every endpoint change with backend.
Simple CRUD APIs (REST is less ceremony). Public APIs (REST is universal; GraphQL has a learning curve). File uploads + downloads (REST handles binary well; GraphQL is awkward). When HTTP caching matters (GET requests cache; POST GraphQL queries don't). When you don't have the team capacity for GraphQL tooling.
Type-first design.
type User {id: ID!email: String!name: String!posts(limit: Int = 10): [Post!]!}type Post {id: ID!title: String!body: String!author: User!}type Query {user(id: ID!): Userusers(limit: Int = 20): [User!]!}type Mutation {createUser(email: String!, name: String!): User!}
gRPC is Google's high-performance RPC framework. Instead of resources and verbs, you define services and methods in a `.proto` file (Protocol Buffers), and gRPC generates strongly-typed client and server code in many languages. It serializes to a compact binary format over HTTP/2, which makes it much faster and smaller on the wire than JSON, and it supports streaming in both directions. Where it shines: internal microservice-to-microservice communication where speed, strict contracts, and code generation matter more than human-readability. Where it does not fit: public browser-facing APIs (browsers cannot speak raw gRPC without a proxy like gRPC-Web, and the binary payloads are not human-friendly). The rule of thumb across all three: REST for public and CRUD APIs, GraphQL for flexible client-driven product APIs, gRPC between your own backend services.
The .proto is the contract; gRPC generates typed client + server stubs from it.
// user.protosyntax = "proto3";service UserService {rpc GetUser (GetUserRequest) returns (User);rpc ListUsers (ListUsersRequest) returns (stream User); // server streaming}message GetUserRequest {string id = 1;}message User {string id = 1;string email = 2;string name = 3;}// `protoc` generates client + server code in Go, TypeScript, Python, Java, etc.// Both sides share the same contract, so a breaking change is a compile error,// not a 3am production surprise.
Picking GraphQL because 'it's modern' without considering team capacity. No DataLoader leading to catastrophic N+1 queries on every nested field. Treating GraphQL mutations like REST POSTs; they're flexible and can mutate many things in one call. Forgetting query depth/complexity limits, letting malicious clients DoS your server with deeply nested queries. Reaching for gRPC on a public browser-facing API, where REST or GraphQL fit far better than binary RPC.
Sign in and purchase access to unlock this lesson.