A user logs into a website on Monday. On Tuesday, they visit the same website and are still logged in. How does the server recognize the returning user, given that HTTP is stateless?
AHTTP maintains a persistent session internally; the server remembers TCP connection history
BThe server stored a cookie on the client during login; the browser sends this cookie with every subsequent request
CThe user's IP address is recorded and used to look up their session automatically
DHTTP/1.1 introduced stateful sessions, so the server maintains login state natively
HTTP itself retains no memory between requests — each request arrives as if the client is a stranger. To simulate state, the server sends a session cookie (a small token) to the browser during login, and the browser includes this cookie in the header of every subsequent request. The server maps that token to the user's session data stored server-side. Option A is wrong: TCP connections have no session semantics at the HTTP level. Option C is unreliable and would break behind NAT. Option D is wrong: HTTP/1.1 added persistent connections, not stateful sessions.
Question 2 Multiple Choice
A client sends 'GET /api/products HTTP/1.1' to a server. According to HTTP semantics, what should the server do?
AReturn a list of products without modifying any server-side data
BCreate a new product entry and return its ID
CDelete the products resource since GET triggers retrieval then cleanup
DReturn an error — GET requests cannot target API endpoints, only HTML pages
GET is explicitly defined as a safe and idempotent method: it retrieves a resource without modifying server state. A GET request should have no side effects. Creating data is the role of POST; replacing a resource is PUT; deleting is DELETE. This is not merely convention — HTTP-aware infrastructure (caches, proxies) rely on GET being safe to cache, replay, or retry without consequences. Using GET to trigger mutations is a violation of HTTP semantics that can cause serious bugs when requests are unexpectedly cached or retried.
Question 3 True / False
HTTP is stateless by design, meaning it is a limitation that developers should work around to build real web applications.
TTrue
FFalse
Answer: False
Statelessness is a deliberate architectural choice, not a limitation. Because each request carries all necessary information (no server-side session memory required), any server in a cluster can handle any request. This makes horizontal scaling straightforward: add more servers and distribute requests freely. A stateful protocol would require all requests from a given user to reach the same server (sticky sessions), complicating load balancing and failover. The 'workaround' — cookies and tokens — is actually the right design: state that exists lives explicitly in the application layer, not hidden in the protocol.
Question 4 True / False
HTTP/3 uses a different underlying transport protocol than HTTP/1.1 and HTTP/2.
TTrue
FFalse
Answer: True
HTTP/1.1 and HTTP/2 both run over TCP. HTTP/3 runs over QUIC, which is built on UDP. QUIC reimplements reliability, ordering, and multiplexing directly in the transport layer, allowing it to combine TCP's guarantees with the ability to avoid head-of-line blocking at the transport level (a limitation of TCP multiplexing in HTTP/2). QUIC also reduces connection setup latency: TLS and transport setup happen in a single round trip instead of multiple. The application-level model — requests, responses, methods, status codes — remains the same across all HTTP versions.
Question 5 Short Answer
What does it mean that HTTP is stateless, and why does this design make web servers easier to scale?
Think about your answer, then reveal below.
Model answer: Stateless means each HTTP request is fully self-contained — the server processes it without any memory of previous requests from the same client. Every request must include all information needed to fulfill it (URL, headers, authentication tokens, etc.). This enables horizontal scaling because any server in a pool can handle any request: there is no session affinity requirement and no shared session state to synchronize. Adding a new server to a cluster requires no migration of client state. Failures are also simpler to handle — a failed server leaves no dangling session that must be recovered.
The trade-off is that statefulness the application needs (login sessions, shopping carts) must be explicitly implemented in the application layer using tokens or cookies — the server looks up a session from a token on each request. This is more visible and controllable than hidden protocol-level state, which is one reason the design ages well: the mechanism for managing state is application code, not an opaque protocol feature.