Mustaque Nadim Academy
Part 1 · Networking

HTTP & APIs

A friend builds a tiny mobile client for Adda, and suddenly two very different programs need to agree on how to talk. HTTP is that shared language; an API is the menu of what you can ask for.

The problem

Word gets around. One of Fahim's friends likes Adda enough to hack together a tiny mobile client for it over a weekend — a scrappy little app that pulls posts and lets you reply, without ever opening the website. Ria is thrilled. She is also, suddenly, in a bind.

Until now the only thing talking to Adda was the browser Ria wrote herself, so she could change both sides at once. Now there is a second client she does not control, written by someone else, that needs to fetch data from her server and make sense of it. The two programs have never coordinated. For this to keep working, both sides must agree — in advance — on the shape of every message: how you ask, how the server answers, how you signal success or failure. Without a shared contract, every new client would need a private, hand-negotiated protocol with Adda, and Ria would spend the rest of her life renegotiating. She needs one language everyone already speaks.

A first attempt

The tempting shortcut: let Adda and each client invent their own private protocol — open a raw TCP socket and send whatever bytes they like, with Ria and each app author agreeing on the format over chat.

It technically works for one pair. But now every new client must learn Adda's private dialect, caches and proxies in the middle cannot understand the traffic, and there is no shared notion of "success," "not found," or "try again." Debugging means reverse-engineering bytes. The moment Adda has a web client, a mobile client, and a third-party app all talking to it, bespoke protocols collapse under their own coordination cost. Ria needs a standard.

The insight

Standardize on a simple, text-based request/response format with a small, fixed vocabulary — and make it stateless so any server can handle any request.

That standard is HTTP. A request names a method (the verb: what you want done), a path (the resource), some headers (metadata), and an optional body. The response carries a status code (a shared three-digit outcome) and its own headers and body. Because each request carries everything needed to understand it, the server keeps no memory of you between requests — and that is what will later let Ria put a whole fleet of interchangeable servers behind a load balancer when Adda outgrows one laptop.

How it works

Ria settles Adda on a clean HTTP API that both the website and the new mobile client speak:

Client sends a request

The client picks a method and path: GET /posts/42. GET reads, POST creates, PUT/PATCH update, DELETE removes. Headers carry auth tokens, content types, and caching hints.

Server maps it to a resource

An API defines what paths exist and what they mean. In REST, paths are nouns (resources) and methods are the verbs acting on them: GET /posts lists posts, POST /posts creates one. Adda runs the logic and builds a response — identical whether the caller is the website or the mobile app.

Server returns a status code

A three-digit code states the outcome in a shared vocabulary — no guessing. 2xx success, 3xx redirect, 4xx you (the client) erred, 5xx the server erred. Plus a body, usually JSON.

Nothing is remembered

The request is stateless: it carried its own auth and context, so Adda needs no session memory of prior calls. The next request can safely land on a totally different server.

A single exchange in the wire's own words:

REQUEST                          RESPONSE
─────────────────────────        ─────────────────────────
GET /posts/42 HTTP/1.1           HTTP/1.1 200 OK
Host: api.adda.com               Content-Type: application/json
Authorization: Bearer <token>    Cache-Control: max-age=60
Accept: application/json
                                 { "id": 42, "author": "Fahim" }

Status codes worth memorizing:

  • 200 OK / 201 Created — it worked.
  • 301 / 302 — moved; follow the redirect.
  • 400 Bad Request / 401 Unauthorized / 403 Forbidden / 404 Not Found — the client's fault.
  • 429 Too Many Requests — you are being rate-limited; back off.
  • 500 Internal Server Error / 503 Service Unavailable — the server's fault; safe to retry later.

The numbers

What the contract actually costs Adda on the wire:

  • Request overhead: an HTTP request/response is typically a few hundred bytes to a few KB of headers, plus the body.
  • Connection reuse (keep-alive / HTTP/2): amortizes the TCP+TLS handshake (~2 round trips, ~60–100 ms) across many requests on one connection — huge for the mobile client, which fires many small calls to paint a feed.
  • HTTP/2 multiplexing: many requests share one connection concurrently, killing the old 6-connections-per-host bottleneck.
  • Idempotency: GET, PUT, DELETE are idempotent — running them twice lands the same final state — so clients and load balancers can safely retry on timeout. POST is not, which is why double-tapping "Post" on a flaky connection can publish Fahim's reply twice.

Statelessness has a cost you pay elsewhere

Stateless requests scale beautifully — any server handles any request, so Ria can add machines freely. But the state has to live somewhere: every request re-sends auth tokens, and session/cart data has to move into a shared cache or database. You trade per-server memory for repeated payload and a dependency on shared storage. That is usually a great trade, but it is a trade.

Idempotency = safe retries

Design write endpoints to be idempotent when you can — accept a client-supplied idempotency key on POST /posts so a retried request is recognized and not published twice. In a world of flaky mobile networks and automatic retries, "exactly once" is bought with idempotency, not wished into existence.

Practice

Recap

  • HTTP is a stateless request/response standard: method + path + headers + body in, status code + body out — one language every Adda client speaks.
  • REST models the system as resources (nouns) acted on by methods (verbs), with status codes as a shared outcome vocabulary.
  • Statelessness enables horizontal scaling (push state to shared storage), and idempotency is what makes retries safe on a flaky network.

In an interview

When you sketch an API, say the endpoints as resource + method (POST /posts, GET /posts/{id}) and call out statelessness explicitly — it is the reason your design can scale horizontally. If writes are involved, mention idempotency keys before the interviewer asks "what if the request is retried?"

How is this guide?

Last updated on

On this page