The Runtime Theory
SystemArchitecturenetwork

What happens when you make an HTTPS request?

A step-by-step walk of one GET: DNS, TCP, TLS, the kernel's send path, server processing, and the response coming back the same way.

The Runtime Theory Team1 min read05 steps

trace spine

  1. 01 Request bytes hit the socket
  2. 02 Kernel send path segments the data
  3. 03 Server reads and parses
  4. 04 Response travels back
  5. 05 Keep-alive amortizes the cost

This is the trace everything else feeds into: DNS resolved, TCP connected, TLS negotiated — now the actual request. A single GET is a small number of kernel crossings wrapped around one network round trip, and nearly everything interesting is in the arithmetic of which round trips you still have to pay.

trace stepApplication

The client writes the request line, headers, and body into the socket — with HTTP/1.1, typically a handful of small writes (~300–800 bytes for a bare GET). send() copies bytes into the kernel's send buffer and returns immediately; the network stack takes it from there. No network activity has happened yet.

trace stepKernel

The kernel segments the buffered bytes into TCP packets (MSS 1460 bytes), encrypts them via the TLS record layer if TLS is in place (which it always is today), and transmits. With TCP_NODELAY, the first segment goes out on the next tick — sub-millisecond. Congestion control allows it immediately since this is a fresh connection in slow start.

trace stepApplication

The server's kernel delivers the bytes to the listening process; the application parses the request line and headers (hundreds of microseconds to a few milliseconds), runs routing, and executes the handler. The time here — framework dispatch, DB queries, rendering — is the only part of the trace the server can optimize; everything else is physics.

trace stepApplication

The response retraces the path in reverse: server application → server kernel → network → client kernel → TLS decrypt → client application. curl -w breaks the total down: time_namelookup, time_connect, time_appconnect, time_starttransfer. On a 40 ms cross-continent link those are roughly 0 (cached DNS) + 40 + 40 + 40 ≈ 120 ms minimum before the first byte — the response body then arrives at line rate.

trace stepApplication

The connection is not destroyed. Both sides keep it open (keep-alive), so request #2 skips the TCP and TLS handshakes entirely: it costs exactly one RTT for the round trip plus server processing. With HTTP/2, many requests share that single RTT simultaneously. One traced GET is the expensive case; a pooled, multiplexed client is the cheap one.

bash
curl -w "\ndns:%{time_namelookup} tcp:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n" -o /dev/null -s https://example.com

The request is the payoff of the three preceding traces, and its own cost is dominated by exactly one number: the RTT. Everything else in this trace — segmentation, parsing, syscalls — is measured in microseconds and happens inside the shadow of the network.