API Styles: REST vs GraphQL vs gRPC
Your mobile team wants one round trip for a screen. Your partner wants a stable URL they can cache. Your services need typed calls inside the mesh. Those are three different API jobs — and picking one style for all of them usually hurts someone.
This article is the style comparison: REST, GraphQL, and gRPC as contract shapes, not audience types. You will see a short skimmer, one representative call per style (with failure shape), and a decision rule by caller. For who may call (Open / Internal / Partner), see Types of APIs. For URL and error conventions, see REST design practices.
Skimmer: which style fits?
REST maps resources to URLs and HTTP verbs — cache-friendly, browser-native, default for public HTTP APIs. GraphQL exposes a query language over one endpoint — clients ask for fields, servers resolve graphs. gRPC is an RPC framework over HTTP/2 with Protocol Buffers — typed stubs, streaming, usually internal.
Decision order: browser or third-party HTTP clients → start REST. Many client screens with divergent shapes from one backend → consider GraphQL. Service-to-service under your control, streaming or high call volume → gRPC. Most production systems layer them: REST or GraphQL at the edge, gRPC behind the gateway.
Quick reference
- REST — resources + HTTP; OpenAPI; CDN caching; over/under-fetch risk.
- GraphQL — one endpoint; client-shaped payloads; N+1 and caching cost.
- gRPC — .proto contracts; binary payloads; not browser-native without a proxy.
- Audience (public vs partner) is a separate axis — see Types of APIs.
- Do not pick a style for "performance" without naming the workload.
Remember this
REST, GraphQL, and gRPC differ in contract shape, not raw speed — pick by who's calling and from where, not by an unscoped performance claim.
REST over HTTP
REST maps resources to URLs and uses HTTP verbs for actions. GET /users/42 returns a user; POST /orders creates an order. Responses are usually JSON — readable, cacheable with standard headers, and supported by browsers, mobile SDKs, and API gateways.
REST shines when the API is public, clients are diverse, and resources map cleanly to nouns. Version via URL (/v1/) or headers; document with OpenAPI. The weakness is over-fetching and under-fetching — a mobile screen needing user + posts + notifications may need several HTTP calls. Auth belongs in headers; see REST authentication methods.
Quick reference
- Best for: public APIs, web apps, third-party integrations, CRUD.
- Transport: HTTP with JSON — human-readable and widely supported.
- Cache-friendly: ETag, Cache-Control, CDN edges on safe GETs.
- Weakness: multiple round trips when a screen needs a graph of resources.
Remember this
REST is the default client-facing style — simple, universal, and cache-friendly.
GraphQL
GraphQL replaces many REST endpoints with a single endpoint (often POST /graphql). The client sends a query for exact fields; the server resolves each field, often by calling internal services or databases. One request can return a user, posts, and notification counts shaped for the screen.
That cuts over-fetching and mobile bandwidth. The cost is server complexity: N+1 resolvers, query depth/cost limits, harder HTTP caching, and DataLoader-style batching. GraphQL fits when web, iOS, and Android need different shapes from the same product graph — not when every client needs the same CRUD resource.
Quick reference
- Best for: complex frontends and dashboards with varied field needs.
- Single endpoint — clients POST queries instead of many REST URLs.
- Enforce depth/cost limits and auth per field — a flexible query is an attack surface.
- Weakness: harder CDN caching than resource GETs; higher server complexity.
Remember this
GraphQL when clients need flexible, shaped data — not as a default for simple CRUD.
gRPC
gRPC is a binary RPC framework commonly used over HTTP/2. Services define contracts in .proto files; generators produce typed client and server stubs. Payloads are Protocol Buffers — compact and fast to parse compared with typical JSON. Unary, server streaming, client streaming, and bidirectional streaming are supported.
gRPC fits internal service-to-service calls where both ends are under your control. Browsers cannot call native gRPC directly — use gRPC-Web behind a proxy (for example Envoy) or keep gRPC internal and expose REST/GraphQL at the edge. Debug with grpcurl or server reflection, not browser DevTools alone.
Quick reference
- Best for: microservices and internal service-to-service communication.
- Transport: HTTP/2 + Protocol Buffers — typed contracts and streaming.
- Tools: gRPC, Protocol Buffers, HTTP/2, grpcurl, Envoy.
- Weakness: not browser-native — proxy or keep internal-only.
Remember this
gRPC for internal typed calls and streams — keep browsers behind REST/GraphQL or gRPC-Web.
Which style should you use?
Most production systems use more than one. The gateway exposes REST or GraphQL to external clients; internal services often speak gRPC. GraphQL resolvers may call gRPC backends under the hood. Layer styles by boundary — do not force one protocol through every hop.
Start with REST for one client type and straightforward resources. Add GraphQL when mobile and web diverge on field shapes. Add gRPC when internal contracts and streaming matter more than human-readable payloads. Avoid hype comparisons that claim a universal winner; measure your call patterns, caching needs, and who owns both ends of the wire.
Quick reference
- Public/browser API → REST (or GraphQL if multiple client shapes).
- Internal service-to-service → gRPC (REST is fine for simple CRUD).
- Mobile/web with divergent screens → GraphQL over many REST endpoints.
- Combine: GraphQL or REST gateway → gRPC backends is a common pattern.
- Auth and rate limits still apply at the edge regardless of style.
Remember this
Layer protocols — REST/GraphQL at the edge, gRPC internally when both ends are yours.
Key takeaway
REST is universal and cache-friendly. GraphQL is client-shaped and flexible. gRPC is typed and stream-capable for internal meshes. None replaces the others — they complement different callers and boundaries.
Practice (20 min): List three callers in your system (browser, partner HTTP client, internal service). Assign REST, GraphQL, or gRPC to each with one sentence of evidence. Then write the success and failure JSON (or gRPC status) for one call on each path.
Related Articles
Explore this topic