System Design Cases
gRPC vs REST vs GraphQL
gRPC vs REST vs GraphQL — three API styles compared. Three vertical columns: REST (resource-oriented HTTP, JSON, OpenAPI, cache-friendly, but suffers over-fetching and N+1); gRPC (HTTP/2, Protobuf, .proto contract, codegen, bidi streaming, ideal for internal microservices, weak browser support); GraphQL (single endpoint, schema, client picks fields, no over/under-fetching, BFF for multiple frontends, but caching is hard and unbounded queries are a DoS vector). Plus a Hybrid block illustrating the Netflix/Twitter/Shopify pattern: REST public + gRPC internal + GraphQL BFF. Four scenarios animate same user-and-posts fetch in each protocol plus a hybrid production path. Includes 4 ADRs for when to pick each, and the hybrid trade-off.
REST, gRPC, and GraphQL: choose contracts, not slogans
REST is an architectural style commonly expressed through HTTP resource semantics. gRPC is an RPC framework with schema-generated APIs and a common HTTP/2 protocol mapping. GraphQL defines a type system, operation language, validation, execution, and response model; its core is transport-agnostic, while GraphQL over HTTP is a separate evolving specification.
Mental model
- The choice is not JSON versus binary. Contract shape, evolution, caching, streaming, browser reach, observability, deadlines, and organizational ownership matter more.
- gRPC commonly uses Protocol Buffers but the framework and protocol concepts must not be reduced to a universal size or speed multiplier.
- GraphQL can reduce client round trips or over-fetching for a screen, but resolver execution can still create fan-out, N+1 access, expensive queries, and partial errors.
- A REST endpoint can return a purpose-built representation; over-fetching and N+1 are API and implementation choices, not inherent REST laws.
Гарантии и границы
- gRPC streams preserve message order within each direction; application side effects still need idempotency and compensation.
- GraphQL validation does not authorize every field or bound execution cost automatically.
- HTTP method idempotency does not make every downstream RPC safe to retry.
- A protocol translation boundary must map deadlines, cancellation, authentication, error detail, and retry ownership explicitly.
Сценарии диаграммы
REST-style HTTP resource contract. A resource-oriented API uses HTTP method, URI, representation, status, caching, and conditional semantics deliberately.
gRPC unary and streaming RPCs. The common gRPC mapping uses HTTP/2 streams, length-prefixed messages, metadata, status, cancellation, and deadlines.
GraphQL selection, resolver fan-out, and partial errors. GraphQL validates a typed operation and executes selected fields; the core specification is transport-agnostic.
Hybrid edge with deadlines and safe retry. Public HTTP contracts can call internal gRPC, but every translation boundary owns deadlines, status mapping, and retry safety.
Архитектурные решения
- Prefer REST-style HTTP for broadly interoperable resource APIs and HTTP caching when those semantics fit.
- Prefer gRPC for schema-first service RPCs and streaming where client/runtime support and HTTP/2 operations are controlled.
- Prefer GraphQL when clients genuinely need flexible typed selection and the platform can enforce field authorization, cost, batching, and schema governance.
Сбои и неоднозначные исходы
- Automatic retries can duplicate mutations across protocol boundaries unless one stable operation identity spans them.
- One overloaded GraphQL query can multiply downstream work; limit by measured cost and resolver budgets, not depth alone.
- A gRPC deadline cancels willingness to wait; it does not roll back a committed write.
Операционный checklist
- Version schemas and test backward/forward compatibility at producer and consumer boundaries.
- Propagate deadlines, cancellation, tracing, identity, and operation keys.
- Budget fan-out, stream count, message size, resolver cost, cache variation, and error detail.
- Load-test the actual payloads instead of citing universal protocol multipliers.