Vetora logo
📡Networking & Protocols

gRPC vs REST vs GraphQL

REST, gRPC, and GraphQL are three dominant API paradigms with different strengths: REST offers simplicity and universal HTTP support, gRPC provides high-performance binary communication with streaming, and GraphQL enables clients to request exactly the data they need.

Overview

REST, gRPC, and GraphQL represent three fundamentally different approaches to API design, each optimized for different constraints. The choice between them is one of the most common architectural decisions in system design, and the answer is rarely 'one size fits all' -- most large systems use two or even all three for different communication boundaries. Understanding the strengths, limitations, and ideal use cases for each paradigm is essential for designing efficient, maintainable distributed systems.

REST (Representational State Transfer) is the most widely adopted API paradigm, built directly on HTTP semantics. REST APIs model the system as a collection of resources (e.g., /users/123, /orders/456) and use HTTP verbs (GET, POST, PUT, DELETE, PATCH) to perform operations on them. Responses are typically JSON, which is human-readable and universally supported. REST's simplicity, statelessness, and compatibility with standard HTTP infrastructure (caches, CDNs, proxies, load balancers) make it the default choice for public APIs. However, REST suffers from over-fetching (returning more fields than the client needs) and under-fetching (requiring multiple round trips to assemble related data), which becomes problematic for mobile clients on slow networks and for complex data aggregation scenarios.

gRPC is a high-performance RPC (Remote Procedure Call) framework developed by Google that uses Protocol Buffers (protobuf) for binary serialization and HTTP/2 for transport. Protobuf messages are 3-10x smaller than equivalent JSON, and binary serialization/deserialization is 5-10x faster. gRPC generates client and server code from .proto definition files, providing strong typing and eliminating manual serialization. HTTP/2 enables multiplexed streams, and gRPC supports four communication patterns: unary (single request, single response), server streaming (one request, stream of responses), client streaming (stream of requests, one response), and bidirectional streaming (streams in both directions). These features make gRPC ideal for internal microservice-to-microservice communication where performance matters. However, gRPC is not browser-friendly (browsers cannot create HTTP/2 connections directly for gRPC), requiring a proxy (grpc-web, Envoy) for web clients.

GraphQL, developed by Facebook and open-sourced in 2015, takes a different approach entirely. Instead of multiple endpoints with fixed response shapes, GraphQL exposes a single endpoint with a strongly-typed schema. Clients send queries specifying exactly which fields they need, and the server returns precisely that data -- no more, no less. This eliminates both over-fetching and under-fetching, which is particularly valuable for mobile clients where bandwidth is constrained and payloads should be minimal. GraphQL also supports mutations (writes) and subscriptions (real-time updates). The trade-off is complexity: GraphQL servers must implement resolvers for each field, and naive resolver implementations suffer from the N+1 query problem (fetching a list of users triggers individual queries for each user's profile). Dataloader pattern batching and query complexity analysis are essential for production GraphQL services.

In practice, most large-scale systems combine these paradigms. A common pattern is REST for public-facing APIs (broad ecosystem support, caching, CDN compatibility), gRPC for internal microservice communication (performance, streaming, code generation), and GraphQL for client-facing API gateways that aggregate data from multiple backend services (flexible queries, reduced round trips for mobile). Understanding where each paradigm fits is more valuable than advocating for one universally.

Key Points
  • 1REST models resources (nouns) with HTTP verbs (GET, POST, PUT, DELETE). It is stateless, cache-friendly, and universally supported by HTTP infrastructure. JSON responses are human-readable but verbose -- a typical REST response includes many fields the client does not need.
  • 2gRPC uses Protocol Buffers (protobuf) for binary serialization, achieving 5-10x smaller payloads and faster serialization than JSON. Code generation from .proto files provides strong typing and eliminates boilerplate. HTTP/2 multiplexing enables efficient concurrent RPCs.
  • 3GraphQL lets clients request exactly the fields they need via a query language, eliminating over-fetching and under-fetching. A single GraphQL request can replace multiple REST calls, reducing round trips -- critical for mobile clients on high-latency networks.
  • 4gRPC supports four streaming patterns: unary, server streaming, client streaming, and bidirectional streaming. This makes gRPC uniquely suited for use cases like real-time data feeds, file uploads, and long-running operations that REST cannot handle efficiently.
  • 5GraphQL's N+1 query problem occurs when resolving a list of entities triggers individual database queries for each entity's related data. The Dataloader pattern solves this by batching and deduplicating database queries within a single request execution.
  • 6The three paradigms are not mutually exclusive. Most large systems use REST for public APIs, gRPC for internal microservices, and GraphQL for client-facing API gateways. The architectural decision is about which boundary uses which paradigm.
Simple Example

The Restaurant Menu Analogy

REST is like ordering from a fixed menu: each dish (endpoint) comes with a predetermined set of ingredients (fields). You cannot remove the garnish you do not want (over-fetching), and if you want a side from a different section, you must place a separate order (under-fetching). GraphQL is like a build-your-own-bowl restaurant: you specify exactly which ingredients you want, and you get precisely that. However, the kitchen needs smart batching to avoid making a separate trip to the fridge for each ingredient (Dataloader for N+1). gRPC is like a direct line to the kitchen where orders are in a compressed shorthand only the staff understands (protobuf) -- extremely fast and efficient, but customers outside the restaurant cannot use the internal radio system (no browser support without a proxy).

Real-World Examples

Google

Google developed gRPC and uses it extensively for internal microservice communication across its infrastructure. Google Cloud APIs also offer gRPC endpoints alongside REST. Internally, gRPC handles billions of RPCs per second with protobuf serialization, HTTP/2 multiplexing, and deadline propagation (each RPC carries a deadline, and downstream services can short-circuit if the deadline has passed). The .proto service definitions serve as the canonical API contract between teams.

GitHub

GitHub migrated from REST (v3 API) to GraphQL (v4 API) to solve the over-fetching and under-fetching problems that plagued integrations. A single REST request to get a pull request with its reviews, comments, and status checks required 4-5 API calls. The GraphQL API allows clients to fetch all of this in a single query, reducing latency and API rate-limit consumption. GitHub's GraphQL API uses persisted queries and query complexity limits to prevent abuse.

Netflix

Netflix uses gRPC for communication between its hundreds of internal microservices, replacing an earlier Ribbon/Eureka REST-based architecture. For client-facing APIs, Netflix built Falcor (a GraphQL predecessor) and later adopted GraphQL Federation to compose a unified API schema from multiple backend services. The API gateway translates GraphQL queries into gRPC calls to backend services, combining GraphQL's flexible querying with gRPC's internal performance.

Trade-Offs
AspectDescription
Performance vs AccessibilitygRPC with protobuf is 5-10x faster than REST with JSON for serialization/deserialization and produces smaller payloads. However, REST's JSON is human-readable, debuggable with curl, and supported by every programming language and HTTP tool. gRPC requires tooling to inspect binary protobuf messages and is not natively supported in browsers.
Query Flexibility vs Caching ComplexityGraphQL's flexible queries solve over-fetching but make HTTP caching nearly impossible because each query is unique. REST's fixed endpoints work with standard HTTP caches (CDN, browser cache) using URL-based cache keys. GraphQL requires application-level caching (Apollo Cache, persisted queries) to achieve comparable caching efficiency.
Strong Typing vs Schema EvolutiongRPC's protobuf and GraphQL's schema both provide strong typing and contract enforcement. REST has no built-in schema enforcement (though OpenAPI/Swagger adds it). However, evolving a gRPC or GraphQL schema requires careful versioning (protobuf field numbers, GraphQL deprecation directives), while REST APIs can evolve more loosely with additive JSON changes.
Server Complexity vs Client SimplicityGraphQL shifts complexity to the server: resolvers, Dataloader batching, query complexity analysis, and N+1 prevention. REST shifts complexity to the client: multiple round trips, manual data assembly, and handling over-fetched data. gRPC generates both client and server code, reducing manual complexity on both sides but requiring protobuf tooling in the build pipeline.
Case Study

GitHub's Migration from REST to GraphQL

Scenario

GitHub's REST v3 API suffered from significant over-fetching and under-fetching. Fetching a pull request with its reviews, review comments, status checks, and labels required 4-5 separate API calls, each returning many unused fields. For GitHub's mobile app and third-party integrations, this meant higher latency (multiple sequential HTTP round trips), wasted bandwidth (transmitting unused JSON fields), and rapid consumption of API rate limits (each call counted against the limit).

Solution

GitHub developed a GraphQL v4 API that exposed the entire GitHub data model as a single, strongly-typed schema. Clients could compose a single query requesting exactly the pull request fields, reviews, comments, and status checks they needed, receiving all data in one response. GitHub implemented persisted queries (clients send a query hash instead of the full query text) to improve performance and prevent abuse. Query complexity limits (measured in 'node cost') prevented expensive queries from overwhelming the server. Resolvers were backed by the same data layer as the REST API, so both APIs coexisted.

Outcome

The GraphQL API reduced the number of API calls needed for common operations by 60-80%. Mobile app load times decreased because a single round trip replaced multiple sequential calls. API rate-limit consumption dropped significantly because one GraphQL request replaced 4-5 REST requests. The strongly-typed schema with introspection enabled better tooling and autocomplete in client IDEs. GitHub continues to maintain both the REST v3 and GraphQL v4 APIs, with new features prioritized for GraphQL.

Common Mistakes
  • Using gRPC for public-facing APIs without a proxy. Browsers cannot create gRPC connections directly. If web clients need to call gRPC services, you need grpc-web with an Envoy proxy, which adds infrastructure complexity. REST or GraphQL is simpler for browser clients.
  • Ignoring the N+1 query problem in GraphQL. Without Dataloader batching, a query for 50 users with their posts can trigger 51 database queries (1 for users + 50 for each user's posts). This can make GraphQL slower than the REST endpoints it replaced.
  • Over-indexing on REST's simplicity and ignoring gRPC for internal services. JSON serialization, text parsing, and lack of streaming make REST significantly slower than gRPC for high-throughput internal communication. The performance gap compounds across a microservice call chain.
  • Building a GraphQL API without query complexity limits. Without limits, a malicious or naive client can submit deeply nested queries that consume enormous server resources. Query complexity scoring and depth limiting are essential for production GraphQL services.
Related Concepts

See gRPC vs REST vs GraphQL in action

Explore system design templates that use grpc vs rest vs graphql and run traffic simulations to see how these concepts perform under real load.

Browse Templates

Benchmark gRPC vs REST vs GraphQL on a social feed

Metrics to watch
p99_latency_mspayload_size_bytesthroughput_rpserror_rate_pct
Run Simulation
Test Your Understanding

1What is the primary advantage of gRPC over REST for internal microservice communication?

2What is the N+1 query problem in GraphQL, and how is it solved?

3Why is HTTP caching harder with GraphQL than with REST?

Deeper Reading