REST vs GraphQL vs gRPC — API Protocol Comparison
In this tutorial, you'll learn about REST vs GraphQL vs gRPC. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
REST vs GraphQL vs gRPC represents the three dominant API protocols in 2026 — each with distinct trade-offs in payload efficiency, schema enforcement, tooling support, and operational complexity.
REST has been the standard for web APIs since the early 2000s, using HTTP verbs and resource-oriented URLs. GraphQL emerged from Facebook as a query language giving clients precise control over response data. gRPC, built on Protocol Buffers and HTTP/2, offers high-performance binary transport ideal for Microservices. This comparison helps you choose based on performance, client needs, streaming requirements, and team expertise.
What You'll Learn
Why It Matters
Choosing the wrong API protocol leads to over-fetching, under-fetching, poor client performance, or excessive operational overhead. REST is simple but can require multiple round trips. GraphQL solves client flexibility but adds query complexity costs. gRPC delivers raw performance but struggles with browser adoption. Understanding these trade-offs helps you match the protocol to your specific client and server requirements.
Who Should Use What
REST suits public APIs, simple CRUD services, and teams prioritizing broad client compatibility. GraphQL suits applications with diverse client requirements, mobile apps needing minimal payloads, and unified data layers. gRPC suits internal Microservices communication, real-time streaming, and performance-critical systems.
flowchart TD
A[Choose API Protocol] --> B{Primary client type?}
B -->|Browser/SPA| C{Data requirements?}
C -->|Fixed, predictable| D[REST]
C -->|Varies per client| E[GraphQL]
B -->|Mobile app| E
B -->|Service-to-service| F{Performance needs?}
F -->|Maximum throughput| G[gRPC]
F -->|Good enough, simpler| D
F -->|Streaming required| G
E --> H{Public API?}
H -->|Yes| I[Consider REST + GraphQL hybrid]
H -->|No| J[GraphQL is fine]
G --> K{Browser support needed?}
K -->|Yes| L[Use gRPC-Web or REST proxy]
K -->|No| M[gRPC is ideal]
Feature Comparison
| Feature | REST | GraphQL | gRPC |
|---|---|---|---|
| Transport | HTTP/1.1 (typically) | HTTP/1.1 or HTTP/2 | HTTP/2 (mandatory) |
| Data Format | JSON, XML, YAML | JSON (query response) | Protocol Buffers (binary) |
| Schema | OpenAPI (optional) | Schema Definition Language (mandatory) | Protocol Buffers (mandatory) |
| Payload Size | Larger (JSON with over-fetching) | Minimal (client specifies fields) | Smallest (binary protobuf) |
| Caching | Native HTTP caching | No native HTTP caching | No native HTTP caching |
| Streaming | Server-Sent Events, chunked | Subscriptions (WebSocket) | Native bidirectional streaming |
| Tooling | Mature (Postman, curl, Swagger) | Good (GraphiQL, Apollo, Relay) | Good (protoc, grpcurl, BloomRPC) |
| Browser Support | Native (XMLHttpRequest, fetch) | Native (fetch, Apollo Client) | gRPC-Web (limited) |
| Learning Curve | Low | Medium | High |
| Versioning | URL or header based | Deprecated fields, schema evolution | Protobuf backward compatibility |
| Error Handling | HTTP status codes | 200 with error list in body | gRPC status codes |
| Code Generation | Manual or OpenAPI generators | Apollo Codegen, graphql-codegen | protoc for 12+ languages |
Performance Comparison
gRPC dominates raw throughput — binary Protocol Buffers with HTTP/2 multiplexing delivers 5-10x lower latency than REST JSON over HTTP/1.1 for high-throughput scenarios. gRPC streaming eliminates polling overhead for real-time data.
GraphQL introduces query parsing and validation overhead on every request, typically 2-5ms per query on the server. For simple resource fetches, REST is faster than GraphQL because there is no query execution cost. For complex data requirements spanning multiple resources, GraphQL is faster than REST because it avoids multiple round trips.
Payload size: gRPC protobuf messages are 60-80% smaller than equivalent JSON. GraphQL responses can be larger than REST if the client requests deeply nested data with many fields. REST with sparse fieldsets (JSON:API sparse fieldsets) approaches GraphQL efficiency but requires server-side implementation.
Code Examples
Fetching a User with Orders
REST
# Two round trips
curl https://api.example.com/users/42
{
"id": 42,
"name": "Alice",
"email": "alice@example.com"
}
curl https://api.example.com/users/42/orders
[
{"id": 1, "total": 29.99, "status": "shipped"},
{"id": 2, "total": 49.99, "status": "pending"}
]
Expected output: Two separate HTTP requests and responses — over-fetching user data and requiring two network round trips.
GraphQL
query {
user(id: 42) {
name
email
orders {
id
total
status
}
}
}
{
"data": {
"user": {
"name": "Alice",
"email": "alice@example.com",
"orders": [
{"id": 1, "total": 29.99, "status": "shipped"},
{"id": 2, "total": 49.99, "status": "pending"}
]
}
}
}
Expected output: Single request returns exactly the requested fields — no over-fetching, single round trip.
gRPC
service UserService {
rpc GetUserWithOrders (UserRequest) returns (UserResponse);
}
message UserRequest {
int32 user_id = 1;
}
message UserResponse {
string name = 1;
string email = 2;
repeated Order orders = 3;
}
message Order {
int32 id = 1;
double total = 2;
string status = 3;
}
# Using grpcurl
grpcurl -d '{"user_id": 42}' api.example.com:443 UserService/GetUserWithOrders
Expected output: Binary protobuf response decoded to JSON — fastest Serialization, smallest payload, single request-response.
Creating a Resource
REST
curl -X POST https://api.example.com/orders \
-H "Content-Type: application/json" \
-d '{"user_id": 42, "items": [{"product_id": 1, "quantity": 2}]}'
{
"id": 3,
"user_id": 42,
"status": "created",
"total": 59.98
}
Expected output: HTTP 201 Created with the new order in the response body.
GraphQL
mutation {
createOrder(input: {userId: 42, items: [{productId: 1, quantity: 2}]}) {
id
status
total
}
}
{
"data": {
"createOrder": {
"id": 3,
"status": "created",
"total": 59.98
}
}
}
Expected output: Same result but always returns HTTP 200 — errors are in the response body, not HTTP status codes.
gRPC
service OrderService {
rpc CreateOrder (CreateOrderRequest) returns (Order);
}
message CreateOrderRequest {
int32 user_id = 1;
repeated OrderItem items = 2;
}
grpcurl -d '{"user_id": 42, "items": [{"product_id": 1, "quantity": 2}]}' \
api.example.com:443 OrderService/CreateOrder
Expected output: Binary protobuf response — strongly typed, compact, and fast to serialize.
Real-time Streaming
REST (Server-Sent Events)
const eventSource = new EventSource("https://api.example.com/orders/stream");
eventSource.onmessage = (event) => {
const order = JSON.parse(event.data);
console.log("New order:", order.id, order.total);
};
Expected output: Server pushes new orders as they arrive — one-way streaming only (server to client).
GraphQL (Subscriptions)
subscription {
orderCreated {
id
total
status
}
}
Expected output: WebSocket-based real-time updates — supports bidirectional communication but requires WebSocket infrastructure and stateful connections.
gRPC (Bidirectional Streaming)
service OrderStream {
rpc OrderFeed (stream OrderFilter) returns (stream Order);
}
stream, _ := client.OrderFeed(ctx)
// Send filter criteria
stream.Send(&OrderFilter{MinTotal: 10.0})
// Receive matching orders in real time
for {
order, _ := stream.Recv()
log.Printf("Order %d: $%.2f", order.Id, order.Total)
}
Expected output: Efficient bidirectional streaming over a single HTTP/2 connection — lowest overhead for real-time data.
When to Choose REST
Choose REST for public APIs consumed by external developers, simple CRUD services, and teams that prioritize broad client compatibility and simple tooling. REST's use of standard HTTP semantics (caching, status codes, content negotiation) works with every browser, tool, and library. REST is also the best choice when you need CDN caching at the HTTP level — GraphQL and gRPC bypass HTTP caching entirely.
When to Choose GraphQL
Choose GraphQL when you have multiple clients (web, iOS, Android) with different data requirements, need to aggregate data from multiple services behind a single endpoint, or want to reduce mobile payload size. GraphQL's schema provides strong documentation and enables tools like Apollo Studio for schema monitoring. GraphQL is ideal for product-centric APIs where client requirements evolve faster than server endpoints.
When to Choose gRPC
Choose gRPC for internal microservice-to-microservice communication, high-performance Data Pipelines, and any system requiring real-time bidirectional streaming. gRPC's protobuf Serialization, HTTP/2 multiplexing, and auto-generated client libraries deliver the best performance for server-to-server communication. gRPC is the default choice for polyglot microservice architectures where performance matters.
Migration Guide
Migrating between API protocols is typically a rewrite of the API layer while preserving business logic. A common intermediate step is to add a GraphQL layer in front of existing REST services using a gateway pattern (Apollo Gateway, GraphQL Mesh). For gRPC Migration, start by wrapping existing REST services with a gRPC gateway (grpc-gateway projects generate REST endpoints from protobuf definitions). Do not attempt to expose gRPC directly to browser clients without a gRPC-Web proxy.
Common Mistakes
- Over-fetching in REST — Returning full resource representations when clients need only a few fields. Use JSON:API sparse fieldsets or query parameter field selection to reduce payload size.
- N+1 queries in GraphQL — A resolver that makes a separate database query for each parent record. Use DataLoader for batching and caching, and monitor resolver performance with tracing tools.
- Ignoring protobuf backward compatibility — Changing field types or removing fields in protobuf breaks existing clients. Always use field deprecation, never reuse field numbers, and add new fields instead of modifying existing ones.
- Using REST for streaming — Polling HTTP endpoints for real-time data wastes bandwidth and increases latency. Use Server-Sent Events for server-to-client streaming or WebSockets for bidirectional communication.
- Exposing gRPC to browsers directly — Browsers lack native gRPC support. Use gRPC-Web as a proxy between browser clients and gRPC servers, or use a REST gateway for browser-facing endpoints.
FAQ
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro