> cs·fundamentals
interview 0% 25m read
2.1 ★ core [J][I] 14 interview Q's

HTTP/HTTPS deeply

Methods + their safe/idempotent semantics, status-code families, the headers that matter, and what TLS adds.

HTTP is a stateless request/response protocol, and almost every backend decision you make rides on two of its properties: the semantics of each method (safe? idempotent?) and the meaning of each status family. Get those right and retries, caching, and error handling mostly fall out for free. The whole protocol is just text on a wire — a method, a path, headers, a blank line, an optional body — and learning to read that exchange fluently is the single most leveraged skill in backend work.

Methods, safety, and idempotency

The interview answer in one breath: GET, PUT, DELETE are idempotent; POST is not; GET/HEAD/OPTIONS are also safe. Two properties, easy to conflate:

  • Safe means read-only — no observable state change on the server. Safe methods are always idempotent (doing nothing N times is still nothing), but the reverse isn’t true.
  • Idempotent means repeatable — calling it once or a hundred times leaves the server in the same final state. The response you get back can differ (the first DELETE /users/42 returns 204, the second returns 404), but the state is identical: the user is gone either way.

Idempotency is the property that lets a client — or a load balancer, or a flaky network, or a retry library — retry without fear. A dropped response to PUT /users/42 is harmless to repeat; you don’t know if the write landed, but repeating it can only converge on the same row. A dropped response to POST /payments is the nightmare case: repeat it and you might charge the card twice. That asymmetry is why payment and order APIs bolt on idempotency keys (covered in 2.2) — they manufacture idempotency for an operation that doesn’t have it natively.

MethodSafe?Idempotent?Typical useWatch out
GETyesyesread a resourcenever let a GET mutate — caches & crawlers replay it
HEADyesyesheaders only, no bodyfor existence/size checks (e.g. Content-Length)
POSTnonocreate / non-idempotent actionretries can duplicate — add an idempotency key
PUTnoyesreplace whole resourceyou must send the full representation
PATCHnonot guaranteedpartial update‘increment by 1’ is non-idempotent
DELETEnoyesremove a resource2nd call returning 404 is fine — state is unchanged
Safe ⊂ idempotent. Memorize the column, not the prose.

Status families and the headers that matter

Read the first digit first, then the exact code. The first digit answers two questions at once: whose fault is it and could a retry ever help.

FamilyMeansKey codesGotcha
2xxsuccess200 OK · 201 Created · 204 No Content201 should set a Location header to the new resource
3xxredirect / cache301 moved · 302 found · 304 Not Modified304 means ‘use your cache’ — it has no body
4xxclient error400 · 401 · 403 · 404 · 409 · 422 · 429401 = not authenticated; 403 = authenticated but forbidden
5xxserver error500 · 502 · 503502/503 from a gateway/overload are safe-ish to retry with backoff
The first digit tells you who is at fault and whether a retry could ever help.

A few codes carry outsized weight in interviews. 409 Conflict is the right answer for a write that collides with the current state (a duplicate unique key, a stale optimistic-lock token). 422 Unprocessable Content means the request was well-formed but semantically invalid (validation failed) — distinct from 400, which is for syntactically broken requests. 429 Too Many Requests is the rate-limit signal and should carry a Retry-After header so the client knows when to come back.

The headers worth knowing cold cluster into four jobs:

  • Identity & authAuthorization: Bearer <token> carries credentials; the server replies WWW-Authenticate on a 401 to say how to authenticate.
  • Content negotiationContent-Type declares the body’s media type; Accept lets the client ask for one. Version-by-content-negotiation rides on these.
  • Caching & concurrencyCache-Control sets freshness rules; ETag is a content fingerprint the client echoes back as If-None-Match (for caching) or If-Match (for optimistic concurrency).
  • CORS — a browser security mechanism. A cross-origin request triggers a preflight OPTIONS that the server must answer with Access-Control-Allow-Origin/-Methods/-Headers, or the browser blocks the real request. CORS is enforced by the browser, not the server — curl ignores it entirely.

A request and response, byte by byte

A request box on the left showing method, path, headers and a JSON body; an arrow to a server; a response box on the right showing a 200 status line, headers, and a JSON body.REQUESTPUT /users/42 HTTP/1.1Host: api.example.comAuthorization: Bearer …Content-Type: application/jsonIf-Match: “a1b2c3”‹blank line›{"name":"Ada"}RESPONSEHTTP/1.1 200 OKContent-Type: application/jsonETag: “d4e5f6”Cache-Control: no-cache‹blank line›{"id":42,"name":"Ada"}
FIG 1 · the HTTP exchange Request line + headers + blank line + body, then a status line + headers + blank line + body coming back. The blank line is what separates headers from body.
An idempotent PUT and its response
PUT /api/v1/users/42 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOi...
Content-Type: application/json
If-Match: "a1b2c3"

{ "name": "Ada", "email": "ada@example.com" }
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "d4e5f6"
Cache-Control: no-cache

{ "id": 42, "name": "Ada", "email": "ada@example.com" }

Send this request three times and the user ends up identical — that is idempotency. The ETag/If-Match pair adds optimistic concurrency: the server compares the If-Match value against the resource’s current ETag and rejects the write with 412 Precondition Failed if someone else changed the row first. This is the read-then-write race solved at the HTTP layer — no locks, just a version check the client opted into.

Conditional GET: 304 saves the body

The flip side of ETag is caching. The client stored a previous response’s ETag and offers it back; if nothing changed, the server skips the body entirely:

GET /api/v1/users/42 HTTP/1.1
If-None-Match: "d4e5f6"
HTTP/1.1 304 Not Modified
ETag: "d4e5f6"

A 304 has no body — it’s a few dozen bytes saying your copy is still good. On a large response this turns a multi-kilobyte transfer into almost nothing, which is exactly why CDNs and browsers lean on it so heavily.

What HTTPS adds, and the handshake

HTTPS is just HTTP carried inside a TLS tunnel — the request/response format above is byte-for-byte identical; it’s simply encrypted in transit. TLS buys you three things: encryption (eavesdroppers see ciphertext), integrity (tampering is detected), and server identity (the certificate, signed by a CA your machine trusts, proves you’re really talking to api.example.com and not an impostor).

The rough handshake (TLS 1.3): the client says hello with the cipher suites it supports; the server replies with its certificate and its half of a key exchange; both sides derive the same shared session key from that exchange (using ephemeral Diffie-Hellman, so even a future leak of the server’s private key can’t decrypt old traffic — forward secrecy); from then on every byte is symmetrically encrypted with that session key, which is fast. The expensive asymmetric crypto happens once, up front, just to agree the cheap symmetric key.

01 Learning objectives

0 / 5 done

02 Curated reading

03 Knowledge check

knowledge check4 questions · pass ≥ 70%
  1. 01easy

    Which HTTP methods are idempotent?

  2. 02easy

    Which status family means “the server failed”?

  3. 03easy

    TLS/HTTPS provides encryption, integrity, and server identity.

  4. 04medium

    A request is well-formed but fails business validation. Best status code?

04 Interview questions

browse all ↗

What gets asked on this topic — tap a card for how to approach it, the follow-ups, and the trap. Company tags are best-effort & sourced.

  • Commonly asked mid concept very common Which HTTP methods are idempotent, and why does it matter?

    GET, PUT, DELETE, HEAD, and OPTIONS are idempotent: making the same call N times leaves the server in the same state as making it once. POST is not idempotent — two POSTs typically create two resources.

    It matters for safe retries. When a client times out it cannot tell whether the request was processed, so it must retry. Idempotent methods can be retried freely; for non-idempotent POSTs you need an idempotency key so the server can dedupe.

    Red flag Conflating idempotent with safe. GET/HEAD/OPTIONS are also safe (no side effects); PUT/DELETE are idempotent but NOT safe. Also: PUT is idempotent by spec even though it changes data.

    source: MDN — HTTP request methods ↗
  • Commonly asked junior concept very common Walk me through the HTTP status code families and name a key code in each.

    Five families by first digit: 1xx informational, 2xx success (200 OK, 201 Created, 204 No Content), 3xx redirection (301 permanent, 302 found, 304 Not Modified), 4xx client error (400 bad request, 401 unauthenticated, 403 forbidden, 404 not found, 409 conflict, 422 unprocessable, 429 too many requests), 5xx server error (500 internal, 502 bad gateway, 503 unavailable).

    The useful instinct: 4xx means the client must change the request; 5xx means the client can retry the same request later.

    Red flag Returning 200 with an error body, or using 401 when you mean 403. 401 = not authenticated (who are you?), 403 = authenticated but not allowed.

    source: MDN — HTTP response status codes ↗
  • Commonly asked mid concept common What is an ETag and how does conditional caching with If-None-Match work?

    An ETag is an opaque validator (often a hash) the server attaches to a response to identify a specific version of a resource. On the next request the client sends If-None-Match: <etag>. If the resource is unchanged the server replies 304 Not Modified with no body, saving bandwidth; if it changed it returns 200 with the new body and a new ETag.

    ETags also enable optimistic concurrency on writes via If-Match: the write is rejected with 412 Precondition Failed if someone else changed the resource first.

    Red flag Thinking 304 carries the body — it does not; the client reuses its cached copy. Also forgetting ETags can prevent lost-update races on PUT.

    source: MDN — ETag ↗
  • Commonly asked mid concept very common Explain CORS. Why does a browser block a cross-origin request, and what is a preflight?

    CORS (Cross-Origin Resource Sharing) is a browser security mechanism on top of the same-origin policy. By default a page at origin A cannot read responses from origin B unless B opts in via Access-Control-Allow-Origin.

    For non-simple requests (custom headers, methods like PUT/DELETE, certain content types) the browser first sends a preflight OPTIONS request. The server answers with Access-Control-Allow-Methods, Allow-Headers, and Allow-Origin; only then does the browser send the real request.

    Red flag Believing CORS is server-side security. It is enforced by the browser; curl, Postman, and a malicious server-to-server call ignore it entirely.

    source: MDN — Cross-Origin Resource Sharing (CORS) ↗
  • Commonly asked mid concept common What does HTTPS/TLS actually add over HTTP, and what is the rough handshake?

    TLS adds three things: confidentiality (traffic is encrypted), integrity (tampering is detected), and server identity (the certificate, signed by a CA, proves you are talking to the real host).

    Handshake sketch: client sends ClientHello (supported ciphers); server returns its certificate and key-exchange parameters; they use asymmetric crypto (e.g. ECDHE) to agree on a shared symmetric session key; the rest of the connection uses fast symmetric encryption. TLS 1.3 cuts this to roughly one round trip.

    Red flag Saying TLS 'encrypts with the certificate'. The cert carries the public key and identity; the bulk data is encrypted with a negotiated symmetric session key.

    source: Cloudflare — What happens in a TLS handshake? ↗
  • Commonly asked mid concept common PUT vs PATCH vs POST for updating a resource — when do you use each?

    PUT replaces the resource wholesale and is idempotent — send the full representation. PATCH applies a partial modification (only the changed fields) and is not guaranteed idempotent by spec. POST creates a new subordinate resource or triggers a non-idempotent action.

    Rule of thumb: full replace at a known URL → PUT; partial field update → PATCH; create-and-let-the-server-assign-the-id → POST.

    Red flag Using PUT for partial updates — sending only some fields with PUT semantically blanks the rest. Use PATCH for partial.

    source: MDN — PUT ↗
  • Commonly asked senior debug occasional A client gets a 200 but you suspect the response was served stale. Which headers control caching, and how would you debug it?

    Caching is governed by Cache-Control (max-age, no-store, no-cache, private/public, must-revalidate), plus validators ETag/Last-Modified and the legacy Expires.

    Debug path: inspect the response Cache-Control and Age headers; check whether an intermediary (CDN/proxy) added Age or an X-Cache: HIT. no-cache means 'revalidate before use', not 'do not cache' — that surprises people. To force freshness set no-store or a short max-age plus an ETag so clients revalidate cheaply with 304s.

    Red flag Reading `no-cache` as 'never cache'. It means store but revalidate every time; `no-store` is the one that forbids storing.

    source: MDN — Cache-Control ↗
  • Commonly asked senior concept occasional What problems did HTTP/2 solve over HTTP/1.1, and what does HTTP/3 change?

    HTTP/1.1 suffers head-of-line blocking: one response per connection at a time, so browsers open many TCP connections. HTTP/2 adds multiplexing (many concurrent streams over one connection), header compression (HPACK), and server push, removing application-layer HOL blocking.

    But HTTP/2 still rides TCP, so a single lost packet stalls all streams (transport-layer HOL blocking). HTTP/3 runs over QUIC (UDP), giving independent streams, faster connection setup (0-RTT), and seamless connection migration across network changes.

    Red flag Claiming HTTP/2 eliminated all head-of-line blocking. It removed it at the HTTP layer but TCP still serializes loss recovery — that's why HTTP/3 moved to QUIC.

    source: Cloudflare — HTTP/3 vs HTTP/2 ↗
  • ★ must-know Commonly asked mid concept very common 401 vs 403 vs 404 — when do you return each, and why might a security-conscious API return 404 instead of 403?

    401 Unauthorized means 'I don't know who you are' — no/invalid credentials; the right fix is to authenticate. 403 Forbidden means 'I know who you are, but you're not allowed' — re-authenticating won't help. 404 Not Found means the resource doesn't exist.

    The security twist: a 403 on a resource you can't see still confirms it exists, leaking information (resource enumeration). Some APIs deliberately return 404 instead of 403 for unauthorized access to private resources, so an attacker can't distinguish 'exists but forbidden' from 'doesn't exist'.

    What a strong answer covers
    • 401 = not authenticated (who are you?); 403 = authenticated but not permitted.

    • Despite the name, 401 means unauthenticated, not unauthorized — a historical misnomer.

    • 403 confirms a resource exists, which can leak information.

    • Returning 404 for forbidden private resources prevents enumeration.

    Quick self-check

    A logged-in user requests another user's private profile they have no rights to see. What's the most information-leak-resistant response?

    Red flag Returning 401 when the user IS authenticated but lacks permission — that's 403. And 403 on private resources silently leaks their existence.

    source: MDN — 403 Forbidden ↗
  • Commonly asked mid concept common What do the SameSite, HttpOnly, and Secure cookie attributes each do?

    HttpOnly hides the cookie from JavaScript (document.cookie), so an XSS payload can't read it — it mitigates token theft. Secure sends the cookie only over HTTPS, so it can't leak over plaintext. SameSite controls whether the cookie rides along on cross-site requests: Strict never sends it cross-site, Lax sends it only on top-level navigations (the modern browser default), and None sends it always but then requires Secure.

    Together they harden a session cookie: HttpOnly+Secure stop theft and eavesdropping; SameSite is the first line of CSRF defense.

    What a strong answer covers
    • HttpOnly → unreadable by JS, blunts XSS-based token theft.

    • Secure → HTTPS-only transmission.

    • SameSite → controls cross-site sending; Lax is the default in modern browsers.

    • SameSite=None must be paired with Secure or the browser rejects it.

    Quick self-check

    Which cookie attribute most directly mitigates CSRF?

    Red flag Thinking HttpOnly prevents CSRF. It stops JS from reading the cookie, but the browser still attaches it automatically on requests — SameSite/CSRF tokens handle CSRF.

    source: MDN — Set-Cookie (SameSite) ↗
  • Commonly asked mid trick occasional Trick: is GET guaranteed to have no server-side effects? Is it safe to cache and retry a GET?

    By the HTTP spec GET is safe (read-only) and idempotent, so intermediaries (browsers, proxies, CDNs) freely cache and retry it. But 'safe' is a *contract you must honor*, not something the protocol enforces — a poorly designed GET /delete?id=5 will happily delete data.

    The danger: because GETs are prefetched, cached, and retried, a side-effecting GET can be triggered by a link prefetcher, a crawler, or a retry, causing unintended mutations. Mutations belong on POST/PUT/PATCH/DELETE; keep GET strictly read-only.

    What a strong answer covers
    • GET is defined as safe + idempotent, but the server must actually honor that.

    • Caches, prefetchers, and crawlers will issue GETs without user intent.

    • A side-effecting GET can fire from a prefetch or retry — a real source of bugs/exploits.

    • Put all mutations behind non-safe methods.

    Quick self-check

    Why is implementing a delete behind GET /delete?id=5 dangerous?

    Red flag Believing the protocol enforces GET's safety. It's a contract — a GET that mutates state is valid HTTP but a design bug that prefetchers and caches will exploit.

    source: MDN — Safe (HTTP methods) ↗
  • Commonly asked senior concept occasional What's the difference between Connection: keep-alive and HTTP/2 multiplexing? Why isn't keep-alive enough?

    Keep-alive (persistent connections, default in HTTP/1.1) reuses one TCP connection for multiple sequential requests, avoiding a new handshake each time. But requests on that connection are still serialized — request 2 waits for response 1 (head-of-line blocking), which is why browsers open ~6 parallel connections per host.

    HTTP/2 multiplexing interleaves many concurrent request/response streams over a single connection, so a slow response doesn't block the others at the application layer. Keep-alive reuses the pipe; multiplexing lets many requests share it simultaneously.

    What a strong answer covers
    • Keep-alive reuses one connection but processes requests sequentially.

    • HTTP/1.1 pipelining tried concurrency but still suffered HOL blocking and was largely abandoned.

    • HTTP/2 multiplexing runs concurrent streams over one connection.

    • Browsers opened ~6 connections per host precisely to work around HTTP/1.1 serialization.

    Red flag Conflating keep-alive with multiplexing. Keep-alive just avoids re-handshaking; it does not allow concurrent in-flight requests on the same connection.

    source: MDN — Connection management in HTTP/1.x ↗
  • Commonly asked senior concept occasional How does HSTS work, and what attack does it prevent that a redirect from HTTP to HTTPS does not?

    HSTS (HTTP Strict Transport Security) is a response header (Strict-Transport-Security: max-age=...) that tells the browser to only ever contact this host over HTTPS for the given duration — the browser upgrades any http:// request to https:// *before* sending it.

    A plain 301 redirect from HTTP→HTTPS still sends that first request in cleartext, which a man-in-the-middle can intercept and strip (SSL stripping). HSTS closes that window because, after the first secure visit (or via the preload list), the browser never makes the insecure request at all.

    What a strong answer covers
    • HSTS forces the browser to upgrade requests to HTTPS before any cleartext goes out.

    • A redirect leaves the initial request exposed to SSL-stripping MITM.

    • The HSTS preload list protects even the very first visit.

    • Set a long max-age; includeSubDomains extends it to subdomains.

    Quick self-check

    What does HSTS protect against that a 301 HTTP→HTTPS redirect alone does not?

    Red flag Assuming an HTTP→HTTPS redirect is fully secure. The first cleartext request before the redirect is interceptable; HSTS (ideally preloaded) is what removes that gap.

    source: MDN — Strict-Transport-Security ↗
  • Commonly asked senior concept occasional A client uploads a large file and the server responds 100 Continue before the body. What is the Expect: 100-continue mechanism for?

    When a client is about to send a large request body, it can send the headers first with Expect: 100-continue and pause before sending the body. The server inspects the headers (auth, content-length limits, content-type) and replies 100 Continue to greenlight the body, or an error status (e.g. 401, 413) to reject it up front.

    The point is to avoid wasting bandwidth uploading a huge body that the server would only reject anyway. It's part of the 1xx informational family — a provisional response before the final one.

    What a strong answer covers
    • Expect: 100-continue lets the client send headers, then wait for a go-ahead.

    • Server replies 100 Continue to accept the body, or an error to reject before upload.

    • Saves bandwidth on large bodies the server would reject (auth fail, too large).

    • 1xx are provisional/informational responses preceding the final status.

    Red flag Treating 100 Continue as a final response. It's provisional — the real status comes after the body is sent and processed.

    source: MDN — 100 Continue ↗