The API is the contract between clients and your system. Designing it well — and knowing REST vs GraphQL vs gRPC tradeoffs and idempotency — sets up everything downstream.
| REST | GraphQL | gRPC | |
|---|---|---|---|
| Style | Resources + HTTP verbs | Single endpoint, client-specified query | Binary RPC over HTTP/2 |
| Best for | Public APIs, CRUD, caching | Rich clients needing varied/aggregated data | Internal service-to-service |
| Wins | Simple, cacheable, ubiquitous | No over/under-fetching; one round trip | Fast, typed (protobuf), streaming |
| Costs | Over/under-fetching; many endpoints | Caching & rate-limiting harder; server complexity | Not browser-native; less human-readable |
Resources are nouns, verbs are HTTP methods:
POST /v1/posts → create a post (returns 201 + id)
GET /v1/posts/{id} → fetch one (200 / 404)
GET /v1/users/{id}/feed?cursor=abc&limit=20 → paginated feed
DELETE /v1/posts/{id} → remove (204)
/v1/) so you can evolve without breaking clients.offset/limit at scale — stable under inserts and O(1) to resume.An operation is idempotent if doing it twice has the same effect as once. GET, PUT, DELETE are naturally idempotent; POST usually isn't (two posts = two records). This matters because networks retry: a client doesn't know if a timed-out request succeeded, so it resends.
The fix for unsafe writes: an idempotency key. The client sends a unique key with the request; the server records it and, on a duplicate key, returns the original result instead of doing the work again. This is how payment APIs guarantee a retry never double-charges.
Authentication ("who are you?") vs authorization ("what may you do?"). Typical pattern: client logs in, gets a token (often a JWT or an opaque session token); an API gateway validates it on every request before traffic reaches your services. Put cross-cutting concerns at this edge: TLS termination, auth, rate limiting, request validation.
Synchronous (REST/gRPC call and wait): simple, but couples services and propagates latency/failure. Asynchronous (publish an event to a queue/bus): decouples services, absorbs spikes, but is eventually consistent and harder to trace. Rule of thumb: synchronous when the caller needs an answer now (e.g., auth check); asynchronous for fan-out side-effects (e.g., "post created → update feeds, send notifications, index for search"). Queues are Unit 08.
Write the API for a URL shortener: the create endpoint, the redirect, and listing a user's links with pagination. Mark which methods are idempotent, choose cursor vs offset pagination with a reason, and say where auth and rate limiting live.