Search Tech Journey

Find topics, journeys and posts

back to blog
engineeringadvanced 12m2026-06-25

Day 27 — API Design — REST, GraphQL, gRPC; Versioning, Pagination, Errors

APIs are contracts that outlive their authors. Bad API design ripples for years; good API design quietly enables product velocity. Knowing when to pick REST / G…

The protocol is the cheap decision; the shape of the API is what lasts. Below: REST vs GraphQL vs gRPC, plus the cross-cutting rules that make any API humane.

🧠 Concept

Why it matters & the mental model.

1. REST — resources + verbs

  • Resources are nouns (/users/42/notes), verbs are HTTP (GET, POST, PUT, PATCH, DELETE).
  • HTTP semantics free: cache headers, status codes, content negotiation.

Pagination + filtering via query params.

  • Good when: external API, browser-friendly, CRUD shapes.
  • Pain: over/under-fetching; many round trips for nested data.

2. GraphQL — client-driven shape

  • Single endpoint; client queries the exact tree of fields it wants.
  • Strong types, introspection, batching via DataLoader.
  • Good when: rich frontends, many devices with different needs.
  • Pain: caching (no HTTP cache for free), N+1 in resolvers, query complexity / DoS surface, schema evolution discipline.

3. gRPC — RPC with strong contracts

  • Protobuf schemas → codegen in many languages.
  • HTTP/2 streaming (server, client, bidi).
  • Excellent for internal microservices: low latency, strong typing, multiplexing.
  • Pain: not browser-native (needs gRPC-Web), opaque on the wire, less BI / debugging tool support.

4. Versioning

  • URL versioning (/v1/users): visible, simple, common.
  • Header versioning (Api-Version: 2024-09-01): cleaner URLs, harder to discover.
  • Stripe-style date-based: pin a date, deprecate slowly, never break — this is the gold standard for B2B APIs.
  • Add additively: new optional fields, new endpoints; remove only after long deprecation window with migration guides.

🛠 Deep Dive

Internals, code, architecture.

5. Pagination

  • Offset/limit: simple, breaks under inserts, expensive at deep offsets.
  • Cursor (opaque token): stable, fast, the modern default. Cursor encodes (sort key, id, direction).
  • Keyset (seek): WHERE id > last_id LIMIT N — same as cursor but exposed. Always include next_cursor / prev_cursor in response, plus optional total_count only if computing it is cheap.

6. Filtering & sorting

  • Stick to flat, well-known params: ?status=active&created_after=2025-01-01&sort=-created_at.
  • For complex filters, consider a dedicated ?filter=... mini-DSL or POST /search with body.
  • Avoid letting clients pass arbitrary SQL/Mongo filters — injection + DoS.

7. Errors — RFC 7807 / Problem Details

{
  "type": "https://api.example.com/errors/insufficient-funds",
  "title": "Insufficient funds",
  "status": 402,
  "detail": "Account 42 has balance 10.00 USD, required 50.00 USD",
  "instance": "/accounts/42/transfers/abc",
  "request_id": "req_01HNZ..."
}

Use machine-readable type, human detail, always include request_id (echo from X-Request-Id).

8. Idempotency

For unsafe operations that may be retried (network blips, mobile), require an Idempotency-Key header. Server stores (key → response) for ~24h and replays on retry. Stripe, GitHub, all serious APIs do this.

🚀 In Practice

Trade-offs, exercises, what to ship today.

9. Rate limiting

  • Token bucket per key/IP/user.
  • Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. On 429, Retry-After.
  • Different buckets for read vs write, for free vs paid.

10. Auth & permissions

  • OAuth 2.1 + PKCE for user auth.
  • API keys for server-to-server (rotate, scope).
  • JWT for stateless; opaque tokens + introspection for revocable.
  • Permissions in the token (claims) or fetched per request (RBAC table). Cache wisely.

11. Observability per request

Every response should carry X-Request-Id. Server-side trace ties together logs, metrics, downstream calls. OpenTelemetry SDKs make this 10-line work.

12. What to take away

"Design an API for X." Strong answers: pick the protocol with reason, define the resource model, show pagination + filter shapes, error format, idempotency, versioning policy. Bonus: mention rate limits and a deprecation strategy.

Key points

    Resources

    Practice Problem: Design Add and Search Words Data Structure (Medium)