How HTTP Works
BeginnerHTTP (HyperText Transfer Protocol) is the language of the web. Every time you load a page, call an API, or submit a form, your browser or application sends an HTTP request to a server and the server sends back an HTTP response. HTTP is a stateless, text-based protocol built on top of TCP/IP. Understanding HTTP deeply — methods, status codes, headers, caching, connections — is foundational for any backend developer because every API, web framework, and proxy speaks it.
Think of HTTP as ordering at a restaurant
You (the client) walk in and give the waiter (the network) your order (HTTP request): "I'd like the GET /menu, please." The waiter goes to the kitchen (the server) and comes back with your food (HTTP response): "200 OK, here is your menu." The waiter doesn't remember you after the interaction — each request is independent (stateless). If you want the waiter to remember your preferences, you give them a note to keep (a cookie). If the kitchen is out of an item, they return "404 Not Found." If the restaurant is closed, you get "503 Service Unavailable."
Step by Step
Key Concepts
Statelessness
HTTP itself carries no memory of previous requests. Each request is independent — the server processes it and forgets. State is managed by the client (cookies, localStorage, session tokens) or stored server-side and identified by a session ID sent in a cookie or Authorization header. This statelessness makes HTTP servers easy to scale horizontally — any server can handle any request because none of them hold session state.
Cookies
Key-value data stored in the browser, sent automatically on every request to the same domain. Set by the server via Set-Cookie response header. Attributes: HttpOnly (no JavaScript access, prevents XSS theft), Secure (HTTPS only), SameSite=Strict/Lax (prevents CSRF by not sending cookies on cross-site requests), Expires/Max-Age (persistence). Session cookies have no Expires and are deleted when the browser closes. Use cookies for session IDs and small auth tokens; not for large application data.
CORS (Cross-Origin Resource Sharing)
Browsers block cross-origin requests by default (same-origin policy). A frontend at app.com cannot call api.other.com without CORS headers. The server must respond with Access-Control-Allow-Origin: https://app.com (or *) to allow it. Preflight: before non-simple requests (POST with application/json), the browser sends an OPTIONS request. The server must respond with the allowed methods and headers. The actual request follows only if the preflight succeeds. CORS is enforced by browsers; server-to-server calls have no CORS restriction.
HTTP Caching
Cache-Control: max-age=3600 allows caches (browser, CDN, proxy) to serve the response for 1 hour without hitting the server. Cache-Control: no-store disables caching entirely (sensitive data). ETag + If-None-Match: the server sends a hash of the content; on the next request, the client sends If-None-Match: <hash>; if unchanged, the server returns 304 Not Modified with no body, saving bandwidth. Last-Modified + If-Modified-Since works similarly with timestamps.
Keep-Alive & Connection Pooling
HTTP/1.1 defaults to Connection: keep-alive — the TCP connection stays open after a response for potential reuse. Without it, every request pays the TCP + TLS handshake cost (~100ms round trips). Backend HTTP clients (Apache HttpClient, OkHttp, Java's HttpClient) maintain a pool of keep-alive connections. Pool exhaustion (all connections in use) causes queuing and latency spikes — size your pool based on expected concurrency.
Key Facts
- HTTP/1.0 closed the connection after every response. HTTP/1.1 made Keep-Alive the default and added Host header (enabling virtual hosting — multiple domains on one IP). HTTP/2 (2015) added multiplexing. HTTP/3 (2022) moved to QUIC (UDP-based). All four versions coexist on the internet today.
- A browser typically opens 6 parallel TCP connections per domain (HTTP/1.1) to work around head-of-line blocking. With HTTP/2, one connection handles all requests to a domain — and HTTP/2 performs better than 6 HTTP/1.1 connections because it avoids TCP slow-start on 5 of them.
- 401 vs 403: 401 Unauthorized means "you are not authenticated — please provide credentials." 403 Forbidden means "I know who you are and you are not allowed." 401 should always include a WWW-Authenticate header telling the client how to authenticate.
- The maximum URL length is not defined in the HTTP spec but is limited by browsers (2,048 chars in IE, much more in Chrome/Firefox) and servers (8KB default in Nginx, 8KB in Tomcat). Use POST with a body for large query parameters instead of encoding them in the URL.
- Content negotiation: the client sends Accept: application/json, text/html to indicate what formats it prefers. The server selects the best match and responds with Content-Type indicating what it sent. This is how a single API endpoint can return JSON for API clients and HTML for browser requests.
Real-World Applications
Debugging slow APIs
Use browser DevTools Network tab or curl -v to see full request/response headers and timing. Time To First Byte (TTFB) is the server processing time. DNS lookup + TCP connect + TLS handshake happen before any HTTP. If TTFB is high, the problem is server-side. If connection time is high, the problem is network or DNS. Response size affects transfer time — enable gzip compression (Content-Encoding: gzip) to reduce payload size 70-90% for text/JSON.
Implementing secure REST APIs
Use HTTPS always — never HTTP for APIs carrying data. Authenticate with JWT in Authorization: Bearer <token> header (not cookies, to avoid CSRF). Set appropriate Cache-Control headers: no-store for user-specific data, max-age=3600 for public data. Return correct status codes (201 for creation, 204 for deletion, 409 for conflicts). Use ETag for optimistic concurrency on PUT endpoints. Rate limit with 429 responses and Retry-After headers.
CDN caching strategy
Static assets (JS, CSS, images with content-hash filenames): Cache-Control: max-age=31536000, immutable — cache for a year, never revalidate (filename changes when content changes). API responses for public data: Cache-Control: public, max-age=60, stale-while-revalidate=30 — serve from CDN cache for 60s, then revalidate in background for up to 30s more. Per-user data: Cache-Control: private, no-store — CDN must not cache it.
Frequently Asked Questions
What is the difference between PUT and PATCH?
PUT replaces the entire resource with the request body. If you PUT a user object with only the email field, the other fields (name, phone) are erased. PATCH applies a partial update — only the fields in the request body are changed. In practice, many APIs implement PATCH semantics even on PUT endpoints. True REST dictates PUT = full replacement, PATCH = partial. For most CRUD APIs, PATCH is safer because clients don't need to send the full resource.
Why does my browser send an OPTIONS request before POST?
This is a CORS preflight. Browsers send OPTIONS first for "non-simple" requests — POST with application/json body, requests with custom headers like Authorization, or methods other than GET/POST. The browser asks the server: "Are you willing to accept this kind of request from this origin?" The server responds with Access-Control-Allow-Methods, Access-Control-Allow-Headers, and Access-Control-Max-Age (how long to cache the preflight result). If the preflight fails, the actual request is never sent. Preflights are cached for Access-Control-Max-Age seconds.
What is the difference between 401 and 403?
401 Unauthorized means the request lacks valid authentication credentials — the client is not logged in or their token is expired. The server should include WWW-Authenticate header to indicate how to authenticate. 403 Forbidden means the client is authenticated (the server knows who they are) but they do not have permission to access the resource. You don't get a second chance to authenticate — access is simply denied regardless of credentials.
How do I prevent CSRF attacks?
Cross-Site Request Forgery exploits cookie-based auth: a malicious site tricks your browser into making authenticated requests to another site where you're logged in. Defences: (1) SameSite=Strict or Lax cookies — browser won't send cookies on cross-site requests. (2) CSRF tokens — server generates a random token, includes it in the HTML form, and verifies it on POST. (3) Use JWT in Authorization header instead of cookies — JavaScript must explicitly set the header, and cross-site JavaScript can't read your headers (SOP prevents it).