HTTP & HTTPS
In a Nutshell
HTTP (HyperText Transfer Protocol) is the request-response language of the web: a client asks for a resource, a server responds with it, using a simple, human-readable structure of methods, headers, and status codes. HTTPS is HTTP wrapped in TLS encryption — it guarantees that no one between the client and server can read or tamper with the traffic, and that the server is who it claims to be. Every web system you design speaks HTTP, so understanding its methods, status codes, statelessness, and how it evolved (HTTP/1.1 → HTTP/2 → HTTP/3) is foundational.

How It Actually Works
Anatomy of a Request and Response
REQUEST RESPONSE
GET /api/users/42 HTTP/1.1 HTTP/1.1 200 OK
Host: api.example.com Content-Type: application/json
Authorization: Bearer eyJ... Cache-Control: max-age=60
Accept: application/json Content-Length: 84
(no body for GET) {"id": 42, "name": "Ada", ...}
Three parts each: a start line (method + path / status code), headers (metadata), and an optional body.
HTTP Methods and Their Semantics
| Method | Purpose | Safe? | Idempotent? |
|---|---|---|---|
| GET | Retrieve a resource | Yes | Yes |
| POST | Create / submit | No | No |
| PUT | Replace a resource fully | No | Yes |
| PATCH | Partial update | No | No (usually) |
| DELETE | Remove a resource | No | Yes |
| HEAD | Like GET but headers only | Yes | Yes |
| OPTIONS | Discover allowed methods (CORS preflight) | Yes | Yes |
Safe = no server state change. Idempotent = repeating it has the same effect as doing it once (critical for safe retries — see API Versioning & Idempotency).
Status Codes at a Glance
| Class | Meaning | Common Examples |
|---|---|---|
| 1xx | Informational | 101 Switching Protocols |
| 2xx | Success | 200 OK, 201 Created, 204 No Content |
| 3xx | Redirection | 301 Moved Permanently, 304 Not Modified |
| 4xx | Client error | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests |
| 5xx | Server error | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable |
The 4xx/5xx split matters for debugging: 4xx is the caller's fault (fix the request), 5xx is the server's fault (retry may help).
HTTP Is Stateless
Each HTTP request is independent — the server remembers nothing between requests by default. State (who's logged in, what's in the cart) is carried explicitly via cookies, tokens (JWT), or a session ID that keys into server-side storage. Statelessness is what makes horizontal scaling of the web tier possible: any server can handle any request.
HTTPS / TLS: Encryption + Identity
HTTPS adds a TLS layer that provides three guarantees:
- Confidentiality — traffic is encrypted; eavesdroppers see gibberish.
- Integrity — tampering is detected.
- Authentication — the server proves its identity via a certificate signed by a trusted Certificate Authority.
TLS handshake (simplified, TLS 1.3):
1. Client Hello → supported ciphers, key share
2. Server Hello → chosen cipher, certificate, key share
3. Both derive a shared session key (via ephemeral Diffie-Hellman)
4. Encrypted application data flows using that symmetric key
(TLS 1.3 does this in ~1 round trip; 0-RTT for resumption)
Asymmetric crypto authenticates and establishes a key; then fast symmetric crypto encrypts the bulk data.
The Evolution: HTTP/1.1 → HTTP/2 → HTTP/3
| Version | Transport | Key Improvement | Limitation Solved |
|---|---|---|---|
| HTTP/1.1 | TCP | Persistent connections, pipelining | New connection per request (1.0) |
| HTTP/2 | TCP | Multiplexing many streams on one connection, header compression, server push | HTTP/1.1 head-of-line blocking at the app layer |
| HTTP/3 | QUIC (UDP) | Independent streams, faster handshake, connection migration | TCP head-of-line blocking at the transport layer |
HTTP/2 fixed application-layer blocking but was still subject to TCP's head-of-line blocking; HTTP/3 moves onto QUIC to eliminate it (see TCP/IP & UDP).

Seeing It in Action
Scenario: Designing cache-friendly, correct HTTP for a REST API.
# Conditional GET — save bandwidth with validators
GET /api/articles/99 HTTP/1.1
If-None-Match: "a1b2c3" # client's cached ETag
HTTP/1.1 304 Not Modified # unchanged → no body resent
ETag: "a1b2c3"
Cache-Control: max-age=300, public # cacheable for 5 min
# Safe retry using idempotency
PUT /api/users/42 HTTP/1.1 # PUT is idempotent
Content-Type: application/json
{"name": "Ada Lovelace"} # retrying is safe — same result
# Rate limiting communicated properly
HTTP/1.1 429 Too Many Requests
Retry-After: 30 # tells the client when to retry
What good HTTP design buys you: ETags + Cache-Control let CDNs and browsers avoid re-downloading unchanged data (a 304 is tiny). Correct method semantics let clients and proxies retry safely. Proper status codes (429 + Retry-After) let clients back off intelligently instead of hammering. This is why "just use HTTP correctly" is itself a scalability strategy.
Interview Questions
Q: What does it mean that HTTP is stateless, and how is state actually maintained? Hint: Each request is independent; the server keeps no memory of prior requests by default. State is carried explicitly: cookies, bearer tokens (JWT), or a session ID that references server-side/Redis session storage. Statelessness enables horizontal scaling — any server can serve any request without sticky affinity.
Q: Which HTTP methods are idempotent, and why does it matter? Hint: GET, PUT, DELETE, HEAD, OPTIONS are idempotent (repeating yields the same result); POST and usually PATCH are not. It matters for safe retries: a client or proxy can safely retry an idempotent request after a timeout without risking duplicate side effects. Non-idempotent operations need idempotency keys to be retry-safe.
Q: Explain what HTTPS/TLS provides and roughly how the handshake works. Hint: Confidentiality (encryption), integrity (tamper detection), and authentication (server proves identity via a CA-signed certificate). The handshake uses asymmetric crypto (certificate + ephemeral Diffie-Hellman) to authenticate and agree on a shared symmetric session key, then bulk data is encrypted with fast symmetric crypto. TLS 1.3 needs ~1 RTT (0-RTT on resumption).
Q: What problem does HTTP/2 solve, and what does HTTP/3 add on top? Hint: HTTP/2 multiplexes many streams over one TCP connection (plus header compression and server push), eliminating application-layer head-of-line blocking and per-request connections. But it still suffers TCP-layer head-of-line blocking. HTTP/3 runs over QUIC (UDP) with independent streams and a faster combined handshake, removing transport-layer blocking and enabling connection migration.
Q: How do you use HTTP features to make an API cache-friendly? Hint: Use
Cache-Control(max-age, public/private) to declare cacheability,ETag/Last-Modifiedvalidators with conditional requests (If-None-Match/If-Modified-Since) so unchanged resources return a tiny304, and appropriate methods (cache GETs, not POSTs). This lets browsers and CDNs avoid redundant transfers, cutting latency and origin load.
References
- MDN HTTP documentation — methods, status codes, headers, caching
- High Performance Browser Networking by Ilya Grigorik — HTTP/1.1, HTTP/2, TLS in depth
- RFC 9110: HTTP Semantics — the authoritative spec
Dive Deeper
- Cloudflare: HTTP/3 explained — the move to QUIC
- Bulletproof TLS and PKI by Ivan Ristić — deep TLS treatment
- How HTTPS works (comic) — an approachable visual walkthrough of TLS