Notes
The contract
An API is a contract. The client never touches your database. It only knows which operations exist, what they take, what they return and which errors can happen. That separation is the point: you can change the database underneath, as long as the contract stays the same.
- the client never sees the DB
- it only sees the API:
- which operations exist
- what inputs they take
- what they return
- which errors can happen
- change the DB freely,
- keep the contract stable
REST
REST is the default for public web APIs. URLs name resources, nouns like users and posts, and the HTTP method is the verb: GET reads, POST creates, PUT replaces, PATCH updates part, DELETE removes. Status codes carry meaning: 200 OK, two oh one created, four hundred bad input, 404 not found, 5xx means it's our bug.
resources are nouns, verbs are HTTP GET /users/42 GET /users/42/posts POST /posts PUT /posts/7 PATCH /posts/7 DELETE /posts/7 200 OK · 201 Created 400 bad input · 404 not found 429 slow down · 500 our bug
RPC
RPC means calling a function on another machine as if it were local: charge payment, send message. gRPC is the popular version: it runs on HTTP two with protocol buffers, so messages are small, binary and strongly typed, and it supports streaming. It shines between your own services; from browsers it's awkward.
call a function on another machine
service Payments {
rpc Charge(ChargeReq)
returns (ChargeResp);
}
gRPC: HTTP/2 + protobuf
binary, typed, fast, streaming
great between services
awkward from browsers Over-fetching
REST has a classic pain. A profile screen needs a name, an avatar and the last three posts with comment counts. With fixed endpoints the app makes several calls, each returning far more fields than it shows. On a slow phone network, those round trips and wasted bytes are what make the screen slow.
- needs: name, avatar,
- last 3 posts, comment counts
- REST gives:
- /users/42 → 40 fields
- /users/42/posts → 50 posts
- /posts/:id/... → per post
- too many round trips
- and too much data
GraphQL
GraphQL flips it. There's one endpoint, and the client sends a query listing exactly the fields it wants, nested: this user's name, avatar, last three posts and their comment counts. One round trip, no wasted fields. The costs: HTTP caching is harder, and a single deep query can be very expensive, so servers limit query depth and cost.
query {
user(id: 42) {
name avatar
posts(last: 3) {
title commentCount
}
}
}
one request, exactly these fields
cost: caching is harder,
and one query can be very expensive Pagination
Never return an unbounded list. Offset pagination, page five hundred, makes the database skip thousands of rows, and items shift when new ones arrive. Cursor pagination says 'give me twenty after this id', which is a fast indexed range query and stays stable while you scroll. Return the next cursor with each page.
offset: ?page=500&size=20 slow: DB skips 10,000 rows rows shift while you scroll cursor: ?after=post_9831&size=20 WHERE id < 9831 ORDER BY id DESC LIMIT 20 fast with an index, stable return next_cursor in the reply
Versioning
Old app versions stay installed for years, so your API can't break them. Adding optional fields or new endpoints is safe. Removing or renaming fields is a breaking change and needs a new version, like slash v two. Also: idempotency keys on POSTs, rate limits per client, and authentication on every endpoint.
- old app versions live for years
- additive changes are safe:
- new optional fields
- new endpoints
- breaking changes need a version:
- /v2/... or a version header
- POST with Idempotency-Key
- rate limits per API key
- auth on every endpoint
Decision
Which one? REST for public APIs and simple create, read, update, delete. gRPC for high-volume calls between your own services. GraphQL when many different clients need flexible, nested data for rich screens. Plenty of large companies use all three, each where it fits.
- public API, simple CRUD → REST
- internal service calls → gRPC
- many clients, rich screens,
- changing needs → GraphQL
- many companies use all three:
- GraphQL for apps,
- gRPC inside,
- REST for partners
Say it like this
In an interview, write three to five endpoints for the core features, with inputs and outputs: post a tweet returns its id, get timeline takes a cursor and returns tweets plus the next cursor. Then say it out loud: REST with JSON, a token for auth, cursor pagination, and idempotency keys on writes.
POST /tweets {text}
→ 201 {id}
GET /timeline?cursor=…
→ {tweets[], next_cursor}
POST /users/:id/follow
say: REST, JSON, auth token,
cursor pagination,
idempotency key on POST