System Design Guide

Fundamentals · 15

API design and real-time communication

REST, gRPC and GraphQL compared; pagination, idempotency and versioning; and how servers push updates with long polling, SSE, WebSockets and webhooks.

3 min read · 6 flashcards

API styles

REST gRPC GraphQL
Shape Resources and HTTP verbs (GET /users/42) Remote procedure calls from a .proto schema One endpoint; the client describes the data it wants
Format JSON (usually) Protocol Buffers (binary) JSON
Strengths Simple, cacheable, universal Fast, typed, streaming, code generation No over- or under-fetching; one round trip for nested data
Weaknesses Over-fetching, many round trips Not browser-native; harder to debug Caching is harder; costly queries need limits
Best for Public APIs, CRUD Internal microservices Mobile and web clients with varied screens

Designing good endpoints

  • Nouns and verbs: POST /tweets, GET /tweets/{id}, DELETE /tweets/{id}, GET /users/{id}/timeline.
  • Pagination:
    • Offset (?page=3&size=20) is simple, but slow deep in a list, and items shift when new ones are inserted.
    • Cursor (?after=<opaque cursor>&limit=20) is stable and fast, which suits feeds and infinite scroll.
  • Idempotency: GET, PUT and DELETE should be idempotent. For POST, accept an Idempotency-Key header. The server stores the result per key, so a retried “charge card” request doesn’t charge twice.
  • Versioning: /v1/… in the path, or a header. Never break existing clients.
  • Errors: correct status codes (400, 401, 404, 409, 429, 5xx) plus a machine-readable body.
  • Rate limits and auth: API keys or OAuth tokens, plus rate limiting with 429 and Retry-After.

Real-time: getting updates to clients

Alice(app)Bob(app)WS gateway 1WS gateway 2Pub/sub(Redis, Kafka)Chat serviceWebSocketWebSocketmessagepublishto Bob's gateway
WebSockets at scale: connection gateways plus a pub/sub layer to reach the right user
Technique How Direction Good for
Short polling Client asks every few seconds Client pulls Simple dashboards; wasteful at scale
Long polling Server holds the request open until there’s data or a timeout Server push (emulated) Fallback where WebSockets fail
Server-Sent Events (SSE) One long HTTP response streams events Server → client Live scores, notifications, LLM token streams
WebSockets Persistent full-duplex TCP connection Both ways Chat, multiplayer games, collaborative editing
Webhooks Your server calls their URL when something happens Server → server Payment events, Git pushes

WebSockets

  • True two-way, low-latency messaging
  • One connection per client, little overhead per message
  • Stateful connections are harder to load-balance and scale
  • Needs a gateway tier and a way to route to the right connection

SSE and long polling

  • SSE is plain HTTP: works through proxies, auto-reconnects
  • SSE is one-way only (the client sends via normal requests)
  • Long polling works everywhere but costs a request per message
  • Both are simpler to run than WebSockets for one-way updates

Test yourself

Answer in your head, then click a card to check. All cards are in the Anki deck.