The journey of a request
Following one HTTP request from a browser tab all the way to your server and back, hop by hop.
Why trace one request
Everything in this course — servers, load balancers, caches, CDNs — is a way of intercepting or shortening some part of a single request's journey. If you can hold the whole journey in your head, every later optimization becomes "which hop are we skipping or speeding up," instead of a new unrelated idea to memorize.
Imagine mailing a letter across the country. You don't personally know the route it takes — you drop it in a mailbox, and a whole system of local post offices, sorting centers, and delivery trucks moves it, hands it off between systems that don't know or care about each other's internals, and eventually a person just like you receives it and can reply the same way. A web request works identically: you just don't usually watch it happen.
Step 1: DNS lookup — turning a name into an address
You typehttps://example.com into a browser. Computers don't route traffic by name, only by IP address, so the very first thing that happens is a DNS (Domain Name System) lookup: your computer asks a DNS resolver "what's the IP address for example.com?" and gets back something like 93.184.216.34.
This lookup is usually cached — by your browser, your OS, and often your router — so it doesn't hit the full DNS system on every single request. The very first time, though, it may hop through several DNS servers (your ISP's resolver, then a root server, then the domain's authoritative server) before an answer comes back.
Browser -> "what's the IP for example.com?" -> DNS resolver -> ... -> authoritative DNS server
Browser <- "93.184.216.34" <----------------------------------------
Step 2: establishing a connection (TCP + TLS)
With an IP address in hand, the browser opens a TCP connection to that address on port 443 (HTTPS) or 80 (HTTP). TCP is a reliable, ordered stream of bytes — it handshakes first (a "SYN, SYN-ACK, ACK" exchange) to agree the connection is open before any real data flows.
If it's HTTPS (almost everything today), a TLS handshake follows immediately: the browser and server agree on an encryption method and exchange keys so everything sent afterward is encrypted and can't be read or tampered with in transit. This is why a browser shows a padlock icon — it's confirming this handshake succeeded and the server's identity was verified by a certificate.
Step 3: the HTTP request itself
Only now does the actual HTTP request get sent — a small block of text (even though it travels as bytes) that looks roughly like:
GET /products/42 HTTP/1.1
Host: example.com
Accept: application/json
Cookie: session=abc123
/products/42), and a set of headers carrying metadata like what response formats are acceptable and any cookies identifying the user's session.
Step 4: routing to the right process on the right machine
The request arrives at the IP address from step 1, which today is rarely a single server — it's typically a load balancer (its own lesson later in this course) that decides which of possibly many identical app servers should actually handle it. That server's OS sees the request arrive on port 443, routes it (as covered in the previous lesson) to whichever process is bound to that port, and your application code finally runs.
Client
→ DNS resolves domain to an IP
→ TCP + TLS handshake to that IP
→ HTTP request arrives at a load balancer (if one exists)
→ routed to one specific app server process
→ app code runs: reads a database, builds a response
→ HTTP response sent back, retracing the same path
Step 5: your app does work, often calling other servers
Inside your app, handling/products/42 typically means asking a database for that product's data — itself a full client/server exchange, just on a private network instead of the public internet. Your app might also call other internal or third-party services (payment processing, an image storage service) before it has everything needed to build a response.
Step 6: the response makes the same trip back
The app builds an HTTP response (a status code like200 OK, headers, and a body — HTML, JSON, whatever the app returns), and it retraces the exact path back: app server → load balancer → the open TCP/TLS connection → the browser, which then renders it or hands the JSON to whatever code asked for it.
The math behind it: where latency actually comes from
Latency is the total time from sending a request to receiving a response. It's the sum of every hop above:
A rough real-world breakdown for a user reasonably close to a server:
| Stage | Typical time |
|---|---|
| DNS lookup (cold) | 20–120 ms |
| TCP handshake | ~1 round trip (10–100 ms depending on distance) |
| TLS handshake | ~1–2 round trips |
| Server processing | 1 ms (trivial) to 500+ ms (heavy query) |
| Network transit (each way) | Roughly proportional to physical distance |
A useful physical floor to know: light in fiber travels at roughly (slower than in a vacuum). A round trip from India to a server in the US East coast (~13,000 km one-way) has an unavoidable physical minimum around:
No amount of software optimization removes this — it's why later lessons on CDNs (serving content from a location physically close to the user) matter so much: they shorten the distance, not just the processing time.
Common mistakes
- Blaming "the server" for slowness that's actually network distance. If most of your latency is transit time to a far-away region, no app-code optimization fixes it — you need a server closer to your users, or a CDN.
- Forgetting DNS and TLS handshakes cost real round trips. These are often invisible in casual testing (browsers cache DNS, keep connections alive) but show up as real cost on a genuinely cold first request.
- Assuming every request talks to only one server. Even a "simple" page load usually fans out into requests to a database, possibly a cache, and sometimes third-party APIs — each with its own version of this whole journey.
- Testing performance only from your own machine. If your server and your test machine are in the same city (or same cloud region), you're measuring a best case that real, distant users won't experience.
A few more concepts worth knowing
- Round trip time (RTT) — the time for a signal to go from client to server and back, the basic unit latency is measured in.
- HTTP status codes — the 3-digit code in every response (
200success,301redirect,404not found,500server error) that tells the client what happened without parsing the body. - Keep-alive connections — reusing one TCP connection for multiple requests instead of re-handshaking every time, a major real-world latency saver.
- HTTP/2 and HTTP/3 — newer versions of the HTTP protocol designed specifically to reduce the handshake and round-trip costs described above for pages with many resources.
Summary
A single request is a chain of hops — DNS, TCP, TLS, transit, processing, transit back — and total latency is just the sum of all of them. Distance and round trips, not just server code speed, are often the dominant cost, which is a big reason "just make the code faster" stops being enough once you have real, geographically spread-out users. With this full picture in mind, the next lesson looks at what breaks first as more of these requests start arriving at the same time.