System Design Space
Knowledge graphSettings

Updated: June 24, 2026 at 7:41 PM

Remote API calls: REST, gRPC, and GraphQL

hard

How to choose between REST, gRPC, and GraphQL: remote-call model, API contracts, schema evolution, latency, caching, and failure behavior.

REST, gRPC, and GraphQL are not competing for one crown; each style wins under a different mix of clients, contracts, and failure modes.

In real design work, the chapter shows how API audience, contract shape, latency tolerance, caching, and backward compatibility should drive the choice more than team preference.

In interviews and engineering discussions, it moves the conversation from API syntax to remote-call behavior: timeouts, retries, fallback, and observability.

Practical value of this chapter

Design in practice

Choose REST, gRPC, or GraphQL based on API audience, contract shape, and latency tolerance.

Decision quality

Define error models, versioning, and backward compatibility as first-class API design concerns.

Interview articulation

Compare styles through client simplicity, observability, caching, and maintenance cost.

Failure framing

Plan partial failures with timeouts, retries, fallback, and circuit breakers.

Source

Remote procedure call

Where the idea of remote procedure calls came from and why the network cannot be fully hidden.

Перейти на сайт

Why compare remote API styles

This chapter treats RPC, REST, gRPC, and GraphQL as different ways to shape the same network dialogue. Arguing about which style feels newer is mostly a waste of time. The real question is where contracts, latency, compatibility, and failure behavior stay easier to control — and what a wrong choice will cost you a year later. This chapter focuses on synchronous call styles; the broader picture of synchronous and asynchronous interaction between services (queues, event streams, publish/subscribe) is covered in “Inter-Service Communication Patterns”.

Standard

OpenAPI Specification

Official format for describing REST contracts, data schemas, errors, and authorization.

Перейти на сайт

The basic remote-call model

Every remote call starts with a client-server model: the client forms a request, the server does the work, and a response comes back. Into the gap between them falls everything that separates a local call from a networked one — serialization, network latency, timeouts, and partial failure. So protocol choice cannot be made apart from the architecture: with it you also choose the contract, the error model, and the operational constraints.

Source

GraphQL Learn

Official introduction to schema, queries, resolvers, and GraphQL practices.

Перейти на сайт

REST, gRPC, and GraphQL: how the styles work

Switch between modes: the diagram shows how request shape, response shape, and contract discipline change.

How remote calls work

Choose an approach to see how request and response are formed

Request and response

Client
call getUser(id)
Server
Client
User
Server

Key properties

  • Procedure call abstraction
  • Focus on methods rather than resources
  • Commonly uses binary serialization

What to keep in mind

Client calls a method as if it were local
Request and response look like function calls
Usually request-response
All four approaches rely on client-server exchange, contracts, and data serialization.

Comparison by key criteria

CriterionRESTgRPCGraphQL
Contract modelHTTP resources with OpenAPI as the external API contract.Interface definition language in `.proto` with generated client and server code.A single graph schema with client-shaped requests for the fields it needs.
Data formatUsually JSON: readable and widely supported, but often larger on the wire.Protocol Buffers: compact and usually cheaper for CPU and network.Usually JSON; response size depends on query shape and caching policy.
Latency and throughputA dependable fit for public APIs and partner integrations.Often better for internal calls with a strict latency budget.Strong client flexibility, but resolver fan-out can become expensive.
API evolutionAPI versioning through URI, headers, or new resources.Field evolution through protobuf rules: field numbers, `reserved`, compatible enums.Schema evolution through deprecation, added fields, and a typed contract.
CachingStrong built-in HTTP caching and proxy support.Caching is usually handled at the client, gateway, or application layer.Needs an explicit strategy: persisted queries, normalized cache, and DataLoader.
Typical fitExternal APIs, partner integrations, and easy adoption across stacks.Internal services, strict contracts, streaming calls, and high-throughput paths.Backend for Frontend, complex UI flows, and multiple client platforms.

Contracts and API evolution

REST and OpenAPI

OpenAPI captures endpoints, parameters, response schemas, errors, and authorization rules. It lowers the risk of breaking external clients.

gRPC and .proto

A `.proto` file defines interfaces, messages, and services. Teams get a strict contract, code generation, and clearer backward-compatibility rules.

GraphQL and schema

Here the schema defines types, fields, and relationships, and the client decides what to ask for. You pay for that flexibility with depth limits, resolver budgets, and observability — otherwise a single query can take down downstream services.

How to choose in real scenarios

Public API for partners

Here REST usually wins: documentation, manual testing, caching, and cross-language integration come almost for free, and the integrator on the other side needn't know your tooling.

Internal service path

Inside the perimeter the picture flips: gRPC's binary format, strict contracts, and low latency matter more than browser-friendly manual calls — that convenience is the thing you can give up.

Mobile and web clients

GraphQL can reduce over-fetching and under-fetching when the schema and resolvers are governed with discipline.

Mixed platform

In practice the styles are combined more often than one is picked: REST at the edge, gRPC between services, and GraphQL or BFF as the client-facing facade. The cost is several contracts and error models you must hold in your head at once.

Common anti-patterns

Choosing API style by trend instead of latency budget, client audience, and operational maturity.
Putting GraphQL over chaotic downstream calls without depth limits, persisted queries, and DataLoader.
Using gRPC without `.proto` evolution rules, contract testing, and a field deprecation policy.
Trying to force one style onto external APIs, internal calls, and client-side data aggregation.

Practical recommendations

Separate API surfaces by audience first: external integrators, internal services, and client applications.
Define backward-compatibility rules before active delivery, not after the first broken client.
Design remote calls as potential partial failures: timeouts, retries, fallback, and circuit breakers.
Compare decisions with signals: p95/p99 latency, error rate, CPU cost, and safe contract-change speed.

What to remember

REST, gRPC, and GraphQL are not fighting for one universal scenario. REST tends to win where external contract clarity and interoperability matter. gRPC is strong for internal service calls with strict schemas. GraphQL is useful as a client-facing facade when the team can govern schema and resolver complexity.

References

Related chapters

Enable tracking in Settings