What Happens When You Type a URL
- The browser works out what to ask (parse, HSTS, caches), where (DNS), how to reach it (ARP to the gateway, then routers), how to talk privately (TCP then TLS), and only then asks (HTTP) and paints (parse, fetch subresources, render).
- A cold HTTPS page costs DNS plus 3 round trips to the edge: 1 for TCP, 1 for TLS 1.3, 1 for the request. TLS 1.2 makes it 4. HTTP/3 makes it 2. A reused connection makes it 1.
- The client ARPs for its default gateway, never for the server. Everything past the gateway is IP routing.
- The IP in the DNS answer is usually a CDN edge or load balancer, not your origin. TLS usually ends there, and the origin sees a second, separate connection.
- Slow first load, fast second load is the signature of cold caches: DNS, connection, TLS session, HTTP cache. Each one is a separate thing to measure.
Mental model
Sending a parcel to a shop you have never visited. You look up the shop's street address in a phone book (DNS). You hand the parcel to your building's front desk, which knows only how to reach the next depot, and the depots pass it on (ARP, then routing). At the shop you ring and wait for someone to answer (TCP handshake), agree on a lock-and-key so the courier cannot read the contents (TLS), and finally say what you want (HTTP). The first visit is slow because of all that set-up; if you keep the line open and ask a second question, it is one quick exchange.
Where it breaks: a parcel goes to one shop. Your request usually lands at a nearby branch of a chain (a CDN edge) that either answers from its own shelf or phones head office on your behalf, and the street address you looked up was the branch's, not head office's.
It is a cold start. Every layer has its own cache and its own set-up cost, and the page load is a pipeline of dependent calls: resolve a name (a service-discovery lookup), open a socket (connect), authenticate and key it (an mTLS-style handshake), then issue the RPC. A warm process skips everything except the last call, the way a connection pool does.
Where it breaks: a connection pool is yours and sits next to your app. Here, each cache belongs to a different party (your OS, your ISP's resolver, the CDN, the origin) with its own expiry rule, so "it is cached" has to be asked at every hop.
How it works
Eight steps. Each one names its layer, what it costs, and the page that owns the detail. This page is the map; follow the links for the depth.
| # | Step | Layer | What happens | Cost, cold | Owner page |
|---|---|---|---|---|---|
| 0 | Parse and local checks | Application | Is this a URL or a search? Check the HSTS list, service worker, HTTP cache, open connections | 0 RTT, microseconds | HTTP caching |
| 1 | DNS | Application (UDP/53) | Name to IP via browser cache, OS cache, recursive resolver, then root, TLD, authoritative | 0 to 1 RTT warm, up to 1 + 3 cold | DNS |
| 2 | First hop (ARP, NAT) | Link and network | ARP for the gateway MAC; router NATs and forwards by IP | Under 1 ms on the LAN | ARP, NAT |
| 3 | TCP handshake | Transport | SYN, SYN-ACK, ACK | 1 RTT | TCP handshake |
| 4 | TLS 1.3 handshake | Between transport and application | ClientHello with SNI and ALPN, server certificate, keys, Finished | 1 RTT (0 on resumption with 0-RTT) | TLS |
| 5 | HTTP request | Application | GET over h2 or h3, with cookies and headers | 1 RTT plus server time | HTTP, HTTP/1.1 and HTTP/2 |
| 6 | Edge, load balancer, origin | Application and network | Edge answers from cache or fetches from origin through a load balancer | 0 on a hit, 1 edge-to-origin RTT on a miss | CDNs, Load balancing, Proxies |
| 7 | Response and render | Application | Cache headers decide reuse; parse HTML, fetch CSS, JS, images, paint | Subresources reuse the open connection | HTTP caching |
The whole path in one picture
The latency ladder
The next figure is the same journey as a time-ordered ladder to the edge, on a cold start with TLS 1.3. Every slanted pair is one round trip. Count the pairs after DNS: three.
Step 0: before any packet leaves
The omnibox decides whether your text is a URL or a search. Then the browser asks, in order, whether it can avoid the network entirely:
- HSTS. If the host is on the browser's built-in preload list, or an earlier visit sent
Strict-Transport-Security(RFC 6797),http://is rewritten tohttps://locally. Without it, the first request goes out in the clear and a301bounces you to HTTPS, which costs a whole extra connection set-up. - Service worker and HTTP cache. A fresh cached copy is served with zero network round trips; a stale one may be revalidated with a conditional request (see HTTP caching).
- Open connections. If a connection to the same origin, or an h2 or h3 connection whose certificate covers this host, is already open, the request skips steps 1 to 4 below.
Parts of a URL go to different places: the host feeds DNS, the scheme and port pick TCP and TLS, the path and query go in the HTTP request line, and the fragment after # never leaves the browser.
Step 1: DNS
The browser needs an IP for www.example.com. It checks its own cache, then asks the OS resolver, which checks its cache and then sends a UDP query to the configured recursive resolver (your ISP, your router, 8.8.8.8). If the resolver has the answer cached it replies in one round trip to itself, typically a few milliseconds. If not, it walks the hierarchy: a root server names the .com servers, a TLD server names the domain's authoritative servers, and the authoritative server returns the record. The recursive resolver caches each answer for its TTL, so most real lookups skip the root and TLD hops. Details, record types and the traps (CNAME chains, negative caching) live in DNS and DNS records and routing.
Browsers usually ask for A and AAAA together and race IPv6 against IPv4 ("Happy Eyeballs", RFC 8305) so a broken IPv6 path does not stall the page. A resolver answer can also include an HTTPS record (RFC 9460) that advertises HTTP/3 support before any connection exists.
Step 2: the first hop, ARP and NAT
The destination IP is not on your subnet, and your host knows that by comparing it against your own address and mask (from DHCP). So the frame is addressed, at layer 2, to your default gateway's MAC address, with the layer-3 destination still the server's IP. If the gateway's MAC is not in the ARP cache, the host broadcasts "who has 192.168.1.1?" and the gateway answers (ARP). That is the only ARP in the whole journey: each later router hop rewrites the MAC addresses and leaves the IP addresses alone, and the server is never ARPed because it is not on your link. On IPv6 the same job is done by Neighbor Discovery (RFC 4861).
At a home or office router, NAT rewrites your private source address and port to the public ones and remembers the mapping so replies come back (NAT). From there, routers forward by longest-prefix match and learn paths between networks via BGP.
Steps 3 to 5: TCP, TLS, HTTP
- TCP (1 RTT). SYN, SYN-ACK, then the client's ACK, which can carry the next layer's first bytes. See the TCP handshake.
- TLS 1.3 (1 RTT). The ClientHello carries the hostname in SNI (RFC 6066), the supported ciphers, a key share, and ALPN (RFC 7301) listing
h2andhttp/1.1. The server picks a version and protocol, sends its certificate chain and finishes; the client verifies the chain and hostname and sends its own Finished. TLS 1.3 needs one round trip before the client can send application data (RFC 8446 section 2); TLS 1.2 needs two (RFC 5246). See TLS. - HTTP (1 RTT). The browser sends
GET /withHost, cookies andAccept-*headers. Over HTTP/2 (RFC 9113) many requests share one TCP connection as streams; over HTTP/3 (RFC 9114) they share one QUIC connection. See HTTP/1.1 and HTTP/2 and HTTP basics.
Step 6: edge, load balancer, origin
The IP from DNS usually belongs to a CDN edge near you (steered by DNS answers or by anycast; see global traffic steering). The edge terminates TCP and TLS, then looks in its cache. On a hit it answers from memory with no origin traffic. On a miss it forwards the request, over a separate and usually already-open connection, to the origin's load balancer, which picks a healthy backend (load balancing). The backend may call a cache, a database, or other services before it responds. The response flows back and the edge stores it if the headers allow (CDNs, proxies and gateways).
Step 7: response, caching and render
The response carries Cache-Control, ETag and Vary headers that tell the browser and every cache on the path how long to reuse it (RFC 9111). The browser starts parsing HTML as the bytes arrive, builds the DOM, and discovers CSS, scripts, fonts and images. CSS and synchronous scripts block rendering, so the first paint waits for them (MDN: critical rendering path). Each new subresource reuses the open connection if it is the same origin, which is why a second request costs one round trip, not four. A different origin (a font host, an analytics host) repeats steps 1 to 5 for itself unless the browser was told to preconnect (web.dev: preconnect and dns-prefetch).
Worked example: the latency budget
Assume, for derivation only: the recursive resolver is 10 ms away, each upstream DNS hop (root, TLD, authoritative) is 40 ms from the resolver, the CDN edge is 30 ms away, the origin is 80 ms from the edge, and the edge has the page cached. Total is the sum of round trips; server think time and transfer time are ignored.
| Scenario | DNS | Transport + TLS | HTTP | Total | RTTs to edge |
|---|---|---|---|---|---|
| Fully cold, TCP + TLS 1.3 (DNS 10 + 3 x 40) | 130 ms | 60 ms | 30 ms | 220 ms | 3 |
| Cold browser, resolver has root and TLD cached (10 + 40) | 50 ms | 60 ms | 30 ms | 140 ms | 3 |
| Resolver cache warm | 10 ms | 60 ms | 30 ms | 100 ms | 3 |
| Browser or OS DNS cache warm | 0 ms | 60 ms | 30 ms | 90 ms | 3 |
| TCP + TLS 1.2 (TLS costs 2 RTT), DNS warm | 0 ms | 90 ms | 30 ms | 120 ms | 4 |
| TCP + TLS 1.3 resumption with 0-RTT, DNS warm | 0 ms | 30 ms | 30 ms | 60 ms | 2 |
| HTTP/3 first contact (QUIC 1-RTT handshake), DNS warm | 0 ms | 30 ms | 30 ms | 60 ms | 2 |
| HTTP/3 resumption with 0-RTT, DNS warm | 0 ms | 0 ms | 30 ms | 30 ms | 1 |
| Reused connection (any version), DNS warm | 0 ms | 0 ms | 30 ms | 30 ms | 1 |
How each row is derived. TCP costs one round trip (30 ms) and TLS 1.3 adds one more (30 ms), so the "Transport + TLS" cell is 60 ms. TLS 1.2 adds two (60 ms), so 30 + 60 = 90 ms. QUIC combines its transport and TLS 1.3 handshake into one round trip (RFC 9000 section 7, RFC 9001), so 30 ms. Resumption lets the client send the request in its first flight (0-RTT, RFC 8446 section 2.3), so TCP's round trip is the only set-up left in the TCP case and nothing is left in the QUIC case.
Cache miss at the edge. Add the edge-to-origin leg. Over an already-open edge-to-origin connection that is one more round trip: 80 ms, so the cold-browser row grows from 140 ms to 220 ms. If the edge must open a new TCP and TLS 1.3 connection to the origin first, add two more round trips, 160 ms, for 240 ms of extra delay in total. This is why edges keep origin connections warm.
The physics floor. Light in fibre travels at roughly two thirds of its vacuum speed, about 200,000 km/s. A 16,000 km path (the New York to Sydney scale used on CDNs) is 16,000 / 200,000 = 80 ms one way and 160 ms round trip at best. A cold three-round-trip load against an origin that far away is therefore at least 480 ms before any server work. A nearby edge shrinks the base of that multiplication from 160 ms to tens of milliseconds, which is the whole business case for a CDN.
TCP slow start adds hidden round trips. A new connection starts with an initial congestion window of 10 segments (RFC 6928), about 10 x 1,460 = 14,600 bytes. The sender roughly doubles each round trip: 14.6 KB, then 29.2 KB, then 58.4 KB, a cumulative 102.2 KB after three flights. So a 100 KB response on a cold connection needs about three round trips of data, two more than the table's single HTTP round trip. This idealised count ignores loss, delayed ACKs and receive-window limits (congestion control).
Deep dive
What breaks at each step
The step that fails tells you the layer, and the browser's error string often names it. Chrome error names are shown; Firefox and Safari word them differently.
| Step | Symptom | Likely cause | First check |
|---|---|---|---|
| DNS | ERR_NAME_NOT_RESOLVED | NXDOMAIN, SERVFAIL, resolver unreachable or all nameservers timing out | dig example.com; try another resolver |
| ARP / first hop | Nothing loads, even the gateway does not answer ping | Not on the network, wrong VLAN, no gateway (DHCP failed) | ip neigh or arp -n, ip route |
| TCP | ERR_CONNECTION_TIMED_OUT | SYNs dropped: firewall DROP, wrong IP, route black hole | nc -zv host 443 |
| TCP | ERR_CONNECTION_REFUSED | Host is up and sent RST: nothing listening, or firewall REJECT | ss -ltn on the server |
| TLS | ERR_CERT_DATE_INVALID, ERR_CERT_COMMON_NAME_INVALID, ERR_SSL_PROTOCOL_ERROR | Expired cert, name mismatch, wrong SNI, no shared protocol version, wrong system clock | openssl s_client -connect host:443 -servername host |
| Edge / LB | 502, 503, 504 | Edge cannot reach or get an answer from a healthy backend | Check LB health checks and origin logs |
| HTTP | 4xx or 5xx from the app | Application logic, auth, bad route | curl -v, server logs |
Timeout versus refused is the pair interviewers love: refused means a machine answered with RST, so the path works and the port does not; timed out means nothing came back, so the packet was dropped somewhere. See the debugging by layer and TCP state machine.
What if DNS fails?
Nothing else can start, because there is no IP to connect to. The stub resolver tries each configured nameserver in turn. On Linux with the glibc resolver the defaults are a 5 second timeout and 2 attempts per server (resolv.conf(5)), so a dead first resolver can add many seconds before the second is tried; browsers often use their own asynchronous resolver with different timing. The three outcomes mean different things: NXDOMAIN (the name does not exist, and that answer is itself cached as a negative cache entry, RFC 2308), SERVFAIL (the resolver could not get a valid answer, for example a broken DNSSEC chain or dead authoritative servers), and a timeout (nobody answered). A resolver may serve an expired cached record while upstream is down ("serve stale", RFC 8767). A CDN cannot help when its own authoritative DNS is the broken part; that is why large sites use several independent DNS providers. See DNS records and routing.
Why is the first request slow?
Because four independent caches are empty: the browser or OS DNS cache, the resolver's cache, the connection (no open socket, no TLS session ticket) and the HTTP cache (nothing stored). Cold load costs DNS plus 3 round trips as derived above; the second page view often pays one. Add the server side: a CDN edge miss, a cold origin, a cold database cache or a function cold start. Isolate which one with curl -w timings (see Hands-on): a large time_namelookup is DNS, the gap to time_connect is TCP, the gap to time_appconnect is TLS, and the gap to time_starttransfer is server wait.
What changes with HTTP/3?
HTTP/3 runs over QUIC, which runs over UDP (RFC 9114, RFC 9000). The transport and TLS 1.3 handshakes merge into one round trip, so cold set-up is 1 RTT instead of 2, and a returning client can use 0-RTT. Loss on one stream no longer stalls the others, because TCP's single ordered byte stream (head-of-line blocking) is gone. QUIC encrypts nearly all of its own header, and connections are identified by a connection ID, so they can survive a Wi-Fi to mobile address change. There is a bootstrap problem: a browser does not know a server speaks h3 until told, by an Alt-Svc header on an earlier HTTP/2 response (RFC 7838) or by an HTTPS DNS record (RFC 9460). If UDP is blocked, the browser falls back to HTTP/2 over TCP. The first visit to a site that has never advertised h3 therefore looks just like the TCP path.
Where does TLS terminate?
Almost always before the origin. At a CDN or cloud edge proxy the client's TLS ends at the edge; the edge opens a second connection to the origin, which may be re-encrypted TLS or, inside a trusted network, plain HTTP. Behind that, a layer-7 load balancer can terminate again or pass TLS through to the backends as raw TCP (a layer-4 choice). The consequences are practical: the certificate the user sees is the edge's, the origin sees the proxy's IP unless it reads X-Forwarded-For or the PROXY protocol, and mutual authentication or end-to-end encryption needs an explicit design. See proxies and gateways and load balancing.
0-RTT is fast and replayable
0-RTT early data is encrypted under a key from a previous session, and the server cannot tell whether the same packet is being replayed by an attacker. RFC 8446 section 8 therefore limits it to requests that are safe to repeat. A proxy that forwards 0-RTT data can mark the request with an Early-Data: 1 header, and the origin can reject unsafe ones with 425 Too Early (RFC 8470). A GET that only reads is fine; a POST /pay is not.
How does the request reach the nearest edge?
Two mechanisms, often combined. DNS steering: the authoritative server returns a different IP depending on where the resolver appears to be. Anycast: many sites announce the same IP prefix via BGP and routing delivers your packets to the topologically closest one. Neither measures real latency directly; both are heuristics, and a user on a distant corporate resolver can be steered wrong. See global traffic steering.
What the journey does not cover
Mobile and Wi-Fi add a radio hop and its own latency (Wi-Fi); a VPN or proxy inserts another connection; corporate TLS inspection terminates and re-originates TLS in the middle; Encrypted Client Hello is being deployed to hide the SNI that this page shows in the clear. Each of those changes the picture without changing the order of the steps.
Textbook vs real world
| The textbook says | Production does | Why |
|---|---|---|
| DNS, then TCP, then TLS, then HTTP, strictly in sequence | Browsers prefetch DNS, preconnect to likely origins, race A and AAAA, and reuse open connections | Round trips are the cost; anything that overlaps or skips one wins |
| The client ARPs for the web server | The client ARPs only for its default gateway; every later hop rewrites the MAC | The server is not on the same link, so no broadcast can reach it |
| Each request opens a connection | HTTP/1.1 keep-alive, HTTP/2 and HTTP/3 multiplex many requests on one | Set-up is 2 to 3 round trips; sharing it amortises the cost |
| TLS adds a full handshake on top of TCP's | TLS 1.3 is 1 RTT, with 0-RTT on resumption; QUIC merges it into the transport handshake | Latency, not CPU, was the cost people noticed |
| DNS returns the server's IP | DNS returns a CDN edge or anycast address, often different per user, with a short TTL | Traffic steering and DDoS absorption live in front of the origin |
| The server terminates TLS | A CDN or load balancer terminates it, and the origin sees a second connection | The edge needs to read HTTP to cache and route, and to keep warm connections to origin |
| Type a URL and the browser sends HTTP | The browser upgrades to HTTPS first when HSTS knows the host, and several browsers now offer HTTPS-first modes | The plain-HTTP first request is the one an attacker can tamper with |
| A page is one request | A typical page is many requests across several origins, each with its own set-up | Third-party hosts repeat the whole journey for themselves |
In production
- Chrome ships an HSTS preload list, so listed sites are HTTPS from the very first visit with no plain-HTTP request to hijack; sites submit themselves at hstspreload.org.
- QUIC and HTTP/3 are deployed at internet scale. Google's 2017 SIGCOMM paper describes running QUIC to Chrome clients and reports its gains concentrated at the slow end of the latency distribution (Langley et al., "The QUIC Transport Protocol: Design and Internet-Scale Deployment"). Cloudflare's HTTP/3 write-up covers the edge side, and Cloudflare Radar publishes the live share of requests by HTTP version; it moves, so check it rather than trusting a number frozen here.
- Preconnect and DNS prefetch are the documented way to hide set-up cost. Chrome's engineering guidance explains that
rel=preconnectdoes DNS, TCP and TLS ahead of the request (web.dev). - TTFB has a published target. The web performance team's guidance treats a time to first byte of 0.8 seconds or less as good, and the figure includes redirects, DNS, connection and TLS, not just server time (web.dev: TTFB).
- Cloud load balancers terminate TLS at the provider edge. Google Cloud's external Application Load Balancer terminates client TLS at Google's front-end proxies (Google Cloud docs), and Amazon CloudFront has separate viewer and origin protocol settings, which means two connections (CloudFront developer guide).
- 0-RTT is offered with a replay guard. Cloudflare's 0-RTT explanation walks through the replay risk and why only safe requests qualify.
History and evolution
- 1982 ARP is specified (RFC 826) so hosts on one Ethernet can map an IP to a MAC without a hand-kept table.
- 1983 The ARPANET moves to TCP/IP. Name lookup is still a shared
HOSTS.TXTfile that does not scale; DNS replaces it, specified in RFC 1034 and 1035 in 1987. - 1991 The first web server and HTTP/0.9: one request, one connection, one document. HTTP/1.0 (RFC 1945) arrives in 1996 and HTTP/1.1 (RFC 2616) in 1997 to 1999 with persistent connections, because a connection per object was too slow.
- 1995 Netscape's SSL brings encryption to the web; TLS 1.0 is standardised in 1999 (RFC 2246). TLS 1.2 handshakes cost two round trips on top of TCP.
- 2012 HSTS (RFC 6797) closes the downgrade hole of the first plain-HTTP request.
- 2015 HTTP/2 (RFC 7540, revised as RFC 9113 in 2022) multiplexes streams on one TCP connection; TCP head-of-line blocking is then the limit.
- 2018 TLS 1.3 (RFC 8446) cuts the handshake to one round trip and adds 0-RTT.
- 2021 QUIC (RFC 9000, 9001, 9002) merges transport and TLS handshakes over UDP; HTTP/3 (RFC 9114) follows in 2022.
- 2023 SVCB and HTTPS DNS records (RFC 9460) let DNS announce h3 support so the first visit can skip the h2 detour.
- Now Most page loads touch a CDN edge, TLS 1.3 and HTTP/2 or HTTP/3; Cloudflare Radar tracks the live split.
- Next Encrypted Client Hello hides the SNI; MASQUE-style proxying pushes more tunnelling into QUIC.
Hands-on
Run these in a terminal against any public site. Timing numbers below are illustrative; yours will differ.
See the phase timings with curl:
These values are cumulative from the start, not per phase. Subtract: DNS 12 ms, TCP 31 ms (one round trip), TLS 32 ms (one round trip, TLS 1.3), then 31 ms from the end of TLS to the first byte (one round trip plus server time). Run it twice; with a warm OS DNS cache the first number shrinks. Add --http2 or --http3 (needs a curl built with HTTP/3) to compare versions, and -w '%{http_version}\n' to print which was used.
Walk DNS yourself:
Output is abbreviated and the final address changes. You see root, then TLD, then authoritative: the cold path from step 1. Note that dig talks to resolvers directly and bypasses your OS cache; to see what the OS itself resolves, use resolvectl query example.com on systemd Linux or dscacheutil -q host -a name example.com on macOS.
Check the ARP entry for the gateway:
The gateway has a MAC entry; the web server's IP has none. That is step 2 in one screen.
Inspect the TLS handshake outcome:
This is OpenSSL 3.x wording; the LibreSSL shipped with macOS formats these lines differently. The ALPN line is how step 5 learns it will speak HTTP/2.
Read the browser's own numbers. In DevTools, open the Network tab, click the first request and read the Timing breakdown (DNS Lookup, Initial connection, SSL, Waiting for server response). Or paste this in the console, using the Navigation Timing fields (W3C spec):
connectStart to connectEnd includes TLS in this API, so tcp here overstates TCP; subtract tls to get TCP alone. A value of zero means that phase was skipped (cached DNS, reused connection).
Gotchas
dig shows what my browser will getInterview questions
Show answer
The browser parses the URL and checks local state: HSTS, caches and open connections. It resolves the hostname to an IP through DNS, ARPs for its default gateway and sends packets through routers, opens a TCP connection with a three-way handshake, and negotiates TLS if the scheme is https. It sends an HTTP request, usually to a CDN edge or load balancer that answers from cache or forwards to a backend, and renders the response while fetching subresources over the same connection.
Follow-ups:
- Which steps cost network round trips? DNS if uncached, 1 for TCP, 1 for TLS 1.3, 1 for the request: DNS plus 3 on a cold HTTPS load.
- Which layer is each step? DNS and HTTP are application, TLS sits between application and transport, TCP is transport, routing is network, ARP is link.
- What is different on a repeat visit? Caches and an open connection cut it to a cache hit (0 round trips) or one conditional round trip.
Show answer
The first visit pays every set-up cost: an uncached DNS lookup, a TCP handshake, a TLS handshake, a cold CDN or origin, and TCP's slow start on a fresh connection. The second reuses the cached DNS record, the open connection and often the HTTP cache. In round trips: cold HTTPS is DNS plus 3 to the edge, a reused connection is 1, and a fresh HTTP cache hit is 0.
Follow-ups:
- How would you tell which part is slow?
curl -wtimings or the DevTools Timing tab: DNS, connect, TLS and wait are separate numbers. - What can you do about it? Preconnect, longer DNS TTLs, a CDN near users, TLS 1.3 and HTTP/3, keep-alive, and cacheable responses.
- Does server speed matter here? It adds to the final wait; it does not touch the three set-up round trips.
Show answer
Nothing else can happen, because the browser has no address to connect to. The stub resolver retries its configured nameservers with timeouts, and the browser eventually shows a name-not-resolved error. The failure mode tells you more: NXDOMAIN means the name does not exist and is cached negatively, SERVFAIL means the resolver could not get a valid answer, and a timeout means nobody answered. Resolvers may serve stale data, and sites mitigate by using several DNS providers.
Follow-ups:
- How do you tell DNS from a connectivity problem? Try the IP directly with
curl --resolveornc; if that works, DNS is the issue. - Does the CDN help when DNS breaks? No, DNS is before the CDN. If the CDN's own authoritative DNS is down, the name is unreachable.
- What about a stale local cache? An old cached A record can send you to a dead IP until the TTL expires.
Show answer
HTTP/3 uses QUIC over UDP. The transport and TLS 1.3 handshakes merge, so a cold connection takes 1 round trip before the request instead of 2, and resumption can use 0-RTT. Streams are independent, so one lost packet no longer stalls the others, and connections survive an IP change through connection IDs. The browser learns about h3 from an Alt-Svc header or an HTTPS DNS record and falls back to HTTP/2 if UDP is blocked.
Follow-ups:
- Why UDP? Middleboxes drop unknown IP protocols and TCP lives in the OS kernel; QUIC in user space can evolve (UDP).
- Is it always faster? Gains are largest on lossy and long paths; on a fast, clean link it is similar to HTTP/2.
- What is the downside? More user-space CPU, and some networks block or throttle UDP.
Show answer
Usually at the edge: a CDN or a cloud load balancer holds the certificate, decrypts the request, and opens a separate connection to the origin, which may be re-encrypted or plain inside a private network. It matters because the edge needs to read the HTTP request to cache and route it, the origin sees the proxy's IP unless told otherwise, and end-to-end encryption or client-certificate authentication needs a deliberate design such as passthrough or re-encryption.
Follow-ups:
- How does the origin learn the client IP?
X-Forwarded-For, theForwardedheader, or the PROXY protocol. - What is TLS passthrough? A layer-4 load balancer forwards the encrypted bytes untouched, so the backend terminates TLS but the balancer cannot route by path.
- Where would you re-encrypt? Whenever the edge-to-origin path crosses a network you do not fully trust.
Show answer
No. ARP maps an IP to a MAC on the same link. If the destination is outside the local subnet, the client ARPs for its default gateway and addresses the frame to the gateway's MAC while keeping the server's IP as the layer-3 destination. Each router then rewrites the MAC addresses for the next link.
Follow-ups:
- How does the client know it is off-subnet? It applies its own subnet mask to the destination and compares the result to its own network.
- How does it learn the gateway? DHCP supplies it, or it is configured statically.
- What is the IPv6 equivalent? Neighbor Discovery, using ICMPv6.
Show answer
HSTS is a header, Strict-Transport-Security, that tells the browser to use HTTPS only for a host for a stated time. Without it, typing example.com first sends plain HTTP and the server redirects to HTTPS; that first request is exposed to a downgrade or tampering attack, and the redirect costs an extra connection. A preload list built into browsers closes the gap for the very first visit.
Follow-ups:
- What does a browser do on an HSTS host? It rewrites the URL to https locally and never sends the HTTP request.
- What is the risk of preloading? It is hard to undo, and every subdomain must support HTTPS.
- Does HSTS stop a bad certificate? It does not fix one, and it removes the click-through for certificate errors on that host.
Show answer
Over TCP with TLS 1.3 it is DNS plus three round trips to the edge: TCP, TLS, request. TLS 1.2 makes it four. You cut them by reusing connections, resuming TLS sessions with 0-RTT for safe requests, using HTTP/3 (two round trips cold, one on resumption), warming DNS and connections with prefetch and preconnect, and moving the edge closer so each round trip is shorter.
Follow-ups:
- Which is bigger, fewer round trips or shorter ones? They multiply, so both matter. A CDN shortens each, QUIC removes one.
- What does TCP Fast Open do? It lets data ride the SYN on resumption (RFC 7413), but middlebox problems kept it rare, and QUIC took that role.
- Why not skip DNS? You can with a hard-coded IP, but you lose failover and steering.
Show answer
Break the time into phases and look at the biggest. curl -w or the browser's timing gives DNS, connect, TLS, wait and download separately. High DNS points to the resolver or an uncached name; high connect points to distance or SYN loss; high TLS points to handshake round trips or certificate chain size; high wait points to the origin or an edge miss; high download points to bandwidth, slow start or MTU. Then compare from another network and against the origin directly to split client-side from server-side.
Follow-ups:
- How do you separate edge from origin? Request the origin directly (or read the CDN's cache-status header) and compare.
- How do you catch packet loss?
mtrandtcpdumpretransmissions; see ping and mtr. - Is the problem always network? No; check server time and page weight too, because TTFB includes everything before the first byte.
Show answer
Refused means the destination host answered the SYN with a RST: the machine is reachable, but nothing is listening or a firewall is rejecting explicitly. Timed out means no reply at all: the SYN was dropped by a firewall that drops silently, a wrong address, or a routing black hole. Linux retries the SYN with exponential back-off and by default gives up after roughly two minutes (kernel ip-sysctl, tcp_syn_retries), which is why a timeout feels so slow.
Follow-ups:
- How do you test each?
nc -zv host portreturns quickly for refused and hangs for filtered. - Which is better for a firewall? DROP hides the host from scanners but makes legitimate failures slow to diagnose; REJECT fails fast.
- What does the browser show? Chrome's ERR_CONNECTION_REFUSED versus ERR_CONNECTION_TIMED_OUT.
Show answer
Two mechanisms. DNS steering returns a different IP depending on the resolver's apparent location. Anycast has many sites announce the same prefix via BGP so routing delivers packets to the nearest one. Both are approximations: DNS sees the resolver, not the user, and anycast follows BGP policy, not measured latency, so providers measure and tune.
Follow-ups:
- What breaks with anycast and TCP? A route change mid-connection can move packets to a different site that has no state, so providers design for it.
- What is EDNS Client Subnet? An extension that passes part of the client's subnet to the authoritative server so it can steer better, at some privacy cost.
- Why short TTLs on edge records? To let the provider move traffic quickly.
Show answer
For the same origin, the browser reuses the open connection: no DNS, no TCP, no TLS, only the request round trip, and a fresh cached copy needs none at all. With HTTP/2 or HTTP/3 many requests are multiplexed on that one connection. A different hostname (an analytics or font host) repeats DNS, TCP and TLS for itself unless it was preconnected, which is why third-party hosts are expensive on a cold load.
Follow-ups:
- What is connection coalescing? HTTP/2 can reuse one connection for another hostname that resolves to the same IP and is covered by the same certificate.
- How long does the connection stay open? Until the server or client idle timeout; it differs by server and browser.
- Does HTTP/1.1 do this too? Yes with keep-alive, but without multiplexing it needs several parallel connections.
Show answer
The server answers the apex name with a redirect, usually a 301 or 308, whose Location header names the www host, and the browser follows it with a second request. That costs another round trip, and a fresh DNS lookup and connection if the www name points elsewhere. The apex cannot be a CNAME because it must also hold the SOA and NS records, so sites that want a CDN hostname on the apex use ALIAS, ANAME or CNAME flattening, or redirect to www and put the CNAME there. See DNS records and routing and HTTP status and semantics.
Follow-ups:
- Why not CNAME the apex? A CNAME means "this name is an alias for that one" and excludes every other record at the name, which collides with the zone's SOA and NS.
- Which redirect code and why? 301 and 302 may turn a POST into a GET; 307 and 308 keep the method. 301 and 308 are permanent and cacheable.
- Why do DevTools show a 307 "Internal Redirect" for http to https? Chrome rewrote the URL locally because of an HSTS entry or an HTTPS upgrade, so no request left the machine (HTTP basics).
Show answer
In layers, nearest first. The browser keeps its own short-lived host cache (Chromium holds system-resolver results for about 60 seconds because the TTL is not visible to it), then the OS stub or its resolver daemon, then often a forwarding resolver on the home router, then the ISP or public recursive resolver, which honours the record's TTL. Each layer can answer without asking the next one, so an answer is only as fresh as the oldest layer that still holds it. See DNS.
Follow-ups:
- Is a home router a recursive resolver? Usually not. Many run a forwarder such as dnsmasq with a small cache (150 names by default) that passes misses to the ISP or a public resolver.
- What does the TTL actually control? How long a cache may reuse the answer. It bounds staleness for the layers that obey it, not when users switch.
- How do you see each layer?
digbypasses the OS stub and asks a server directly, whilegetaddrinfocallers (browsers,curl) go through the stub, so they can disagree.
Show answer
Possibly. Chrome pre-resolves the hostname of omnibox suggestions, and for high-confidence or search suggestions it may also open a TCP connection ahead of time. A page can ask for the same with preconnect or dns-prefetch hints, and the Speculation Rules API can prefetch or prerender a likely next page. The visible consequence is a server that sees a connection which never carries a request. The exact heuristics change between Chrome versions, so state the mechanism, not the numbers. See HTTP caching for what a prefetched response may do afterwards.
Follow-ups:
- Why is that worth it? DNS plus TCP plus TLS are the setup cost; moving them before the click removes up to three round trips from the visible load.
- What is the downside? Wasted connections and, for prerender, wasted server work and analytics noise for pages the user never opens.
- Which hint do you add as a site owner?
preconnectfor the one or two third-party origins the page certainly needs, since each preconnect holds a socket open.
Show answer
The omnibox first decides whether the text is a URL or a query. Browsers use a mix of syntax checks and history and do not publish the exact rules, so a bare word with a dot can go either way. If it is a query, the journey is the same walk to the search provider's URL. Back is different: a page held in the back/forward cache is restored with no network at all, while a normal back navigation may revalidate against the HTTP cache. A page with an unload handler or Cache-Control: no-store is usually ineligible for the back/forward cache. See HTTP caching.
Follow-ups:
- What is the difference between reload and hard reload? A normal reload revalidates cached entries with conditional requests, a hard reload bypasses the cache and refetches everything.
- Which caches can answer before any socket opens? HSTS state, the HTTP memory and disk cache, a service worker, the back/forward cache, and a prefetched or prerendered page. The DNS cache and socket pool remove the setup steps rather than the request.
- Where does a service worker sit? In front of the HTTP cache: it intercepts the fetch first and may or may not call through to the network.
Show answer
The scheme chooses the port and whether TLS runs. The host is used for DNS, goes in the TLS SNI field and in the HTTP Host header (or :authority in HTTP/2 and HTTP/3). The path and query go in the request line. The fragment after # never leaves the browser, so the server cannot see or route on it. A non-ASCII hostname is converted to Punycode (the xn-- form) before DNS. See HTTP basics.
Follow-ups:
- Why does Host exist? HTTP/1.1 allowed many sites on one IP, and SNI exists for the same reason one layer down.
- Is the query string private under HTTPS? It is encrypted on the wire, but it lands in server and proxy logs and can leak through the Referer header unless a policy limits it.
- What is an IDN homograph attack? A hostname that looks like a trusted one using lookalike characters from other scripts, which is why browsers may show the Punycode form for suspicious mixes.
Show answer
Treat it as three known causes and test each. A race in connection tracking for UDP can drop one of the two parallel A and AAAA queries, and the stub resolver waits out its timeout (5 seconds by default) before retrying. ndots:5 search-list expansion multiplies the query count. An overloaded CoreDNS makes everything slower. Fingerprint with conntrack -S (insert failures), per-query timing with dig from inside the pod, and CoreDNS metrics. Mitigations are NodeLocal DNSCache, fully qualified names, and scaling CoreDNS. See Kubernetes networking.
Follow-ups:
- Why is the stall a multiple of the resolver timeout? The lost query is only noticed when the stub times out, so the delay is the timeout, not network latency.
- Why does NodeLocal DNSCache help? Most lookups are answered from a cache on the node, so far fewer queries cross the conntrack path where the race happens.
- What is a good probe? Run the lookup from the affected pod with
dig +tries=1 +time=2against each resolver, not from your laptop.
Show answer
The TTL is how long a cache may keep the answer, so every layer that cached it before the change keeps serving the old value until its own entry expires. Some resolvers clamp or extend TTLs (one measurement study found about 9% of resolvers extending them), negative answers are cached for the SOA minimum, some runtimes cache for a long time, and long-lived connections never re-resolve at all. Lower the TTL one old-TTL period before the change, and keep the old endpoint serving until traffic to it reaches zero. See DNS.
Follow-ups:
- How far ahead do you lower the TTL? At least one full old TTL before the change, since caches filled with the long TTL will not look again until it runs out.
- Does a low TTL make failover instant? No. Failover speed is bounded by the TTL plus every resolver that ignores it.
- What is a safer pattern? Keep a stable name and move the target behind it, such as a load balancer or anycast address.
Show answer
Not usually. A busy recursive resolver already holds the root's referrals and the TLD delegations for common TLDs: TLD NS records carry a 48-hour TTL, and typically under 1% of queries need to contact a root server at all. So most uncached lookups cost one or two round trips from the resolver, to the TLD and the authoritative server, and the client sees one round trip to its resolver plus whatever the resolver does. Only an empty resolver cache really walks from the root. See DNS.
Follow-ups:
- How often do users cause a root query? About one per user per day on average, per APNIC measurements.
- What does
dig +tracedo differently? It makes your machine act as the recursive resolver and walk root, TLD and authoritative itself, ignoring any resolver cache. - Why QNAME minimisation? The resolver sends only the labels each server needs, so root and TLD servers see less of the name; it adds some packets and does not encrypt anything.
Show answer
Almost everything at first. Resolvers cache TLD delegations for about two days, so lookups under already-cached TLDs keep working and only each TLD's refresh needs a root. As caches expire, failures grow: an ISOC hypothetical puts it near 2% of queries failing per hour, trending to near-total failure around 48 hours if nothing is done. The root is also not one machine: there are 13 named identities served by well over a thousand anycast instances, and resolvers can run a local copy of the root zone (RFC 8806). See DNS and global traffic steering.
Follow-ups:
- Why does DNSSEC matter here? Signatures on cached data have validity windows, so a long outage eventually makes validated answers expire as well.
- What is the root negative-cache TTL? One day, so a nonexistent TLD stays "not found" for that long.
- What dies first? Names under TLDs a resolver has never cached, and anything with a short TTL that needs a fresh authoritative answer.
Show answer
NXDOMAIN says the name does not exist at all. NODATA (an empty answer with success) says the name exists but has no record of that type. SERVFAIL says the resolver could not get a valid answer, for example the authoritative servers are unreachable or DNSSEC validation failed. Negative answers (NXDOMAIN and NODATA) are cached for the smaller of the SOA record's TTL and its minimum field (RFC 2308), and RFC 9520 says resolvers should also cache resolution failures for a short time so they do not hammer broken servers. See DNS records and routing and error messages.
Follow-ups:
- Why does caching failures matter in an outage? It limits the retry storm; during the 2021 Facebook outage resolvers still retried and query volume rose about 30x.
- How does negative caching bite after a launch? If you query a name before creating it, resolvers keep saying NXDOMAIN for up to the SOA minimum after you add it.
- Which of the three points at the authoritative side? SERVFAIL, since NXDOMAIN and NODATA are valid answers from a reachable authority.
Show answer
Both. Queries normally go over UDP for one-packet cost, but TCP is a required part of the protocol (RFC 5966). A server sets the TC bit when the answer does not fit, the client retries over TCP, and zone transfers (AXFR, IXFR) use TCP. EDNS0 lets a client advertise a bigger UDP size, and the 2020 DNS Flag Day moved the common default to 1232 bytes to avoid IP fragmentation. A truncated answer costs the extra UDP round trip plus the TCP handshake. See DNS and MTU, MSS and fragmentation.
Follow-ups:
- What if a firewall blocks TCP/53? Small answers still work, so it passes casual tests, but large DNSSEC or truncated answers fail intermittently.
- Why not make TCP the default? Per-query state and a handshake cost for what is usually a one-packet exchange.
- What do DoT and DoH change? They encrypt the query on port 853 and 443 respectively, which helps privacy and hides it from enterprise filtering.
Show answer
A spoofing attacker races the real answer and must match the query's 16-bit transaction ID. Kaminsky's insight was to query random non-existent names under the target domain, so each attempt is a fresh race, and to put forged glue and additional records in the reply that overwrite the nameserver entry for the whole domain. The fix was to randomise the UDP source port, adding about 16 bits of entropy, with 0x20 case randomisation and bailiwick checks as extras. DNSSEC is the real answer because it authenticates data, not just the transport. See DNS and network attacks.
Follow-ups:
- How can NAT undo source-port randomisation? A PAT device that remaps ports predictably can shrink the entropy the resolver thought it had.
- What does DNSSEC not protect? Confidentiality, and the last mile from a validating resolver to the client unless that hop is secured too.
- Why random names? A name already cached cannot be raced again until its TTL expires; random names are always uncached.
Show answer
Because the answer can depend on who asks. GeoDNS or latency-based DNS picks an address by the resolver's location, EDNS Client Subnet (ECS) lets the resolver pass a truncated client prefix (such as a /24 for IPv4) so the authority can steer by the user instead of the resolver, split-horizon DNS gives internal and external clients different answers, and anycast gives the same address a different physical destination. The authoritative server normally sees only the resolver's IP, so a user behind a distant resolver can be sent to a far edge. See global traffic steering and CDN.
Follow-ups:
- Is anycast the same as GeoDNS? No. Anycast gives the same DNS answer and lets routing choose the site, while GeoDNS gives different answers.
- Who sends ECS? Google Public DNS does; Cloudflare's 1.1.1.1 deliberately does not, so DNS-steered CDNs map those users by resolver location.
- What does ECS cost? User privacy, and cache entries per client prefix, which lowers hit rates at the resolver.
Show answer
DNS returns a virtual IP chosen by location and load. Edge routers spread packets by ECMP to Maglev, Google's software load balancer, which hashes the 5-tuple, keeps a connection table, and uses consistent hashing so a flow stays on one backend. Packets then reach a Google Front End, which terminates TCP and TLS near the user, inspects the HTTP request, and forwards it over persistent, re-encrypted connections to the right backend. Terminating at the edge means the handshake round trips are paid on the short leg. See load balancing and system request path.
Follow-ups:
- What is stabilized anycast? If BGP lands a packet at a site that does not own the flow, Maglev forwards it to the site that does, so route changes do not reset connections.
- Why not assign frontends purely by geography? Load and capacity matter too, so DNS balances proximity against load.
- Why does a single VIP help DNS? The address rarely changes, so the TTL can be longer.
Show answer
Compare the same asset from a healthy region and an affected one and subtract the curl -w fields, holding everything else constant. Then branch: a high DNS time means a far resolver or no ECS and a wrong edge; high connect time means distance or anycast landing on a distant site; high TLS time means extra round trips or a large chain; high TTFB means an edge cache miss or a long edge-to-origin path. Segment by ASN and ISP, not only country, and check recent edge configuration changes. The mitigation is to steer DNS or withdraw anycast from the bad site, with failover speed bounded by TTLs for the DNS route. See debugging by layer and CDN.
Follow-ups:
- How do you tell which edge served you? Read the CDN's response header that names the PoP and cache status.
- Why compare by ASN? One ISP's peering or routing can be the whole problem while the rest of the country is fine.
- Why check config pushes? A recent edge change is a common cause of a regional regression, and rolling it back on one group first limits the blast radius.
Show answer
The IP source and destination addresses stay the same end to end, except where NAT rewrites them. The router decrements the TTL (and recomputes the header checksum), strips the incoming Ethernet frame, and builds a new one with its own source MAC and the next hop's destination MAC, which it finds by an ARP lookup on that link. So the layer-2 header is rewritten at every hop while layer 3 is preserved. See host forwarding decision, forwarding and longest prefix match and ARP.
Follow-ups:
- What happens when the gateway never answers ARP? Local traffic works but nothing leaves the subnet, which is the classic "can ping neighbours, not the internet" pattern.
- Does ARP cross routers? No, the broadcast stays on the local link.
- What do switches do with the ARP broadcast? Flood it out all ports except the one it arrived on, learning source MACs into the CAM table as frames arrive.
Show answer
The connection never reached the application. Look at the listen queues: if the accept queue is full because the app is slow to call accept, the kernel drops the final ACK or the SYN and the client sees a timeout rather than a refusal. Other candidates are a full SYN backlog under a SYN flood (SYN cookies encode state in the sequence number to survive it), a conntrack table that is full, or a firewall dropping silently. Check ss -ltn for Recv-Q against the backlog, nstat listen-overflow counters, and conntrack -S. See TCP connection and TCP state machine.
Follow-ups:
- Why does a full accept queue look like a timeout, not a refusal? Nothing sends an RST; the packets are dropped and the client retransmits the SYN.
- What do SYN cookies cost? Some TCP options may be lost, because the server stores nothing and has to fit the state in the sequence number.
- How would you notice before users do? A black-box prober outside the network, plus alerts on listen-overflow counters.
Show answer
The client thinks the connection is established and may start sending data. The server is still in SYN_RECEIVED, so it retransmits its SYN-ACK on a timer. When the client's next segment arrives it carries the ACK flag with the right acknowledgement number, which completes the handshake on the server. If the server's retries are exhausted first, it gives up and a later client segment is answered with a reset. Linux retries the SYN-ACK a bounded number of times. See TCP connection and TCP state machine.
Follow-ups:
- Why is this asymmetry possible? The client reaches ESTABLISHED when it receives the SYN-ACK, but the server only gets there when the final ACK arrives.
- How long does a server keep trying? About 63 seconds in total with Linux defaults (TCP connection).
- What does it look like in
ss? Half-open connections pile up as SYN-RECV on the server.
connect starts failing. Do the maths.seniorShow answer
The side that closes first keeps the 4-tuple in TIME_WAIT for 60 seconds on Linux. With the default ephemeral range of 28,232 ports, one client IP can open about 28,232 / 60, roughly 470, new connections per second to a single destination IP and port before connect fails with EADDRNOTAVAIL. So at 10,000 per second the answer is not tuning but reuse: pool and keep connections alive, and add source addresses or destinations. Size the pool with Little's Law: connections needed is request rate times service time. See port exhaustion and TIME_WAIT.
Follow-ups:
- Why not set
tcp_tw_recycle? It was removed in Linux 4.12 because it broke clients behind NAT;tcp_tw_reusehelps only outgoing connections. - Which side holds TIME_WAIT? Whoever closes first, which is why proxies and clients suffer more than servers.
- How is CLOSE_WAIT different? It means the peer closed and your application never called
close, so it is an application bug that leaks sockets until it hits the limit.
Show answer
Nagle's algorithm holds a small segment while earlier data is unacknowledged, and the receiver's delayed ACK holds the acknowledgement waiting for data to piggyback it on. On a pattern of two small writes, each side waits for the other, which produces the stall. It needs both mechanisms together, not Nagle alone. The fix for latency-sensitive traffic is TCP_NODELAY, or coalescing writes into one. See Nagle and delayed ACK.
Follow-ups:
- How do you prove it? A packet capture shows the second small segment waiting roughly a delayed-ACK interval for the ACK of the first.
- Why not turn Nagle off everywhere? It exists to avoid flooding the network with tiny packets for bulk byte-at-a-time writers.
- What is
TCP_CORKfor? It holds partial frames until you uncork, for assembling headers and body into full segments.
Show answer
Slow start. A new connection begins with an initial congestion window of 10 segments, about 14.6 KB, and roughly doubles each round trip, so it cannot send the whole response at once. 200 KB is about 137 segments, which needs windows of 10, 20, 40 and 80, so around three extra round trips after the first flight. This is why connection reuse and warm pools matter, and why a connection that idles may drop back to slow start. See congestion control and TCP performance.
Follow-ups:
- Does HTTP/3 fix it? Only partly: QUIC runs its own congestion controller with a similar slow start, so a new connection still ramps up.
- What resets the window after idle? Linux's
tcp_slow_start_after_idlesetting. - Why is the first flight special? A server that can answer within about 14 KB finishes in a single round trip, which is why critical HTML is kept small.
Show answer
A path-MTU black hole. The handshake, health checks and small requests fit in the path MTU, but a full-size segment with the DF bit set is too big at some hop, and the ICMP "fragmentation needed" message that should tell the sender to shrink is filtered, so the sender retransmits the same size forever. Find the threshold by sweeping payload sizes, for example ping -M do -s 1472, and check with tcpdump icmp. Fixes are allowing ICMP type 3 code 4, clamping MSS on the tunnel, enabling tcp_mtu_probing, or lowering the tunnel or overlay MTU. See MTU, MSS and fragmentation.
Follow-ups:
- What is the modern cause? Encapsulation: an overlay such as VXLAN adds about 50 bytes, so a standard 1500-byte path no longer carries a full frame.
- Does plain
pingtest it? Not without the DF bit set. - Why does MSS clamping not help QUIC? It only rewrites the TCP MSS option, and QUIC runs over UDP.
Show answer
In TLS 1.2 the first round trip negotiates versions and ciphers and delivers the certificate, and the second finishes key exchange. TLS 1.3 sends the client's key share in the first flight, so the server can reply with its key share, certificate and Finished in one round trip, and everything after ServerHello is encrypted. Forward secrecy is mandatory because 1.3 dropped RSA key transport and static Diffie-Hellman. Resumption can send application data in the first flight (0-RTT), but that data is replayable. See TLS.
Follow-ups:
- An attacker records traffic now and steals the server key next year. Can they read it? Not with ephemeral key exchange: past sessions stay safe, but the key still lets them impersonate the server from then on.
- When is 0-RTT safe? Only for idempotent requests, and the server needs anti-replay protection, since RFC 8446 gives no replay guarantee for early data.
- Does TLS 1.3 save a round trip over TCP? It costs one on top of TCP's own handshake. QUIC is what folds the two together.
Show answer
The TLS session encrypts and authenticates the HTTP content with keys the attacker never sees, and the certificate check stops them from impersonating the server. What still leaks is metadata: the destination IP, the SNI hostname unless Encrypted Client Hello is used, traffic timing and size, and DNS queries unless they use DoH or DoT. A padlock only shows that the server holds the key for that name, not that the site is trustworthy. See TLS and certificates and PKI.
Follow-ups:
- What does ECH need? Keys published in the HTTPS DNS record, and a server that opts in; Chrome has shipped it since version 117.
- What does a valid padlock not prove? That the site is honest, that its validation was not disabled by the client, or that no rogue CA was trusted.
- What does HSTS add? It removes the plain HTTP first hop and the click-through option, which stops SSL stripping on known hosts.
Show answer
It points at trust and chain building, not the handshake. The two clients use different trust-anchor sets and different path-building: Chrome ships its own root store and fetches a missing intermediate through the certificate's AIA field, while curl, Python, Java and Go generally do not fetch it and fail. So a server that omits its intermediate works in the browser and fails in API clients. Debug with openssl s_client -showcerts to see the chain actually served, and test the same IP with the expected hostname. See certificates and PKI and curl and openssl.
Follow-ups:
- Does Chrome use
/etc/ssl/certs? No, it ships its own roots, and Firefox uses its own store as well. - Why not fix it only on the client? The server should serve the full chain, because relying on clients to fetch intermediates is fragile.
- What other differences cause this? SNI missing when connecting by IP, cipher or version mismatch, client clock skew, and ALPN.
Show answer
Suspect an expired certificate or an expired intermediate first, because the cutover to a new day is a classic expiry moment and a handshake failure leaves servers idle. Test from outside the network with openssl s_client -connect host:443 -servername host and read the verify error and the chain. Then check whether the renewal ran but the proxy never reloaded the new file, whether ACME failed after a DNS change, or whether rate limits blocked issuance. Prevent it with expiry alerts at 30 and 14 days, an external prober, and automated renewal that is exercised regularly. See TLS and certificates and PKI.
Follow-ups:
- Why test from outside? Your own monitoring may use an internal path or a trust store that hides the failure.
- Renewal worked for months, then every client fails. Why? The cert may be renewed but not deployed, the wrong chain served, or the clients' trust store changed.
- What does short-lived certificate lifetime do? It forces the automation to work constantly, so a broken pipeline shows up early.
Show answer
A very large ClientHello. Hybrid post-quantum key shares make it exceed one 1,500-byte packet, so it is split across TCP segments, and a middlebox or proxy that reads only the first segment misparses the SNI and drops or stalls the connection. Real reports exist for ingress-nginx and for a cloud network firewall with newer OpenSSL. Test by forcing -no_tls1_3 or a smaller key share in openssl s_client, and capture the handshake to see where it stops. Another candidate with the same symptom is a path-MTU black hole dropping a large certificate flight. See TLS and debugging by layer.
Follow-ups:
- Why only some clients? Only clients that send the large key share are affected; older clients send a smaller hello.
- What is the proper fix? Make the proxy reassemble the hello across segments instead of reading only the first.
- Where is the break relative to ServerHello? If the client never gets a ServerHello it is the hello; if the stall is after it, suspect the certificate flight and MTU.
Show answer
Because the browser does not know the site speaks HTTP/3. A cold client typically starts with HTTP/2 over TCP, learns about HTTP/3 from an Alt-Svc header on that response or from an HTTPS DNS record, and uses QUIC on later connections. When an HTTPS record with alpn=h3 is present Chrome can attempt QUIC without waiting for a prior response, racing it against TCP. If UDP on port 443 is blocked it falls back to TCP and remembers the failure. See QUIC and HTTP/3 and HTTP/1.1 and HTTP/2.
Follow-ups:
- Does HTTP/2 fix head-of-line blocking? At the HTTP layer yes, but it inherits TCP's, so one lost segment stalls every stream on the connection.
- Does QUIC remove all shared fate? Loss recovery is per stream, but the congestion window is still shared by the connection.
- What operational gaps does UDP bring? Load balancers and observability tooling built for TCP may not handle it.
Show answer
A keep-alive mismatch. If the backend closes idle connections sooner than the load balancer's idle timeout (60 seconds by default on an ALB), the balancer can reuse a socket the backend just closed and gets a reset, which it reports as 502. The failures are random and low-rate. Confirm by checking which party generated the response (an ALB log shows elb_status_code 502 with target_status_code of - when the balancer made it), and fix by making each hop's idle timeout longer than the one in front of it. See load balancing, proxies and gateways and error messages.
Follow-ups:
- Why does it show up more at low traffic? Idle connections are the ones that expire, and busy connections never sit idle long enough.
- Which other causes align with deploys? Backends that exit on SIGTERM without draining, oversized headers, and an upstream that closes early.
- How do 502, 503 and 504 differ? 502 is a bad or no response from upstream, 503 is no healthy capacity, 504 is an upstream timeout.
Show answer
A green check only proves what the check tests. If the health path returns 200 unconditionally, or the check is TCP-only, it says nothing about real serving. Real traffic can fail on a different path: an exhausted connection pool, a TLS mismatch that only the real hostname triggers, or one bad zone or subset. Make the check represent readiness, drain or remove the bad subset first, and avoid a check that depends on a shared database, which can mark every backend unhealthy at once. See load balancing and cloud load balancers.
Follow-ups:
- What belongs in a health check? The ability to serve a real request; not shared dependencies whose failure would drain the whole fleet.
- What does deregistration delay do? It lets in-flight requests finish before a target is removed; the AWS default is 300 seconds.
- How does the staff-level answer differ? It adds blast radius and prevention: probes that match real traffic, canary scope and automatic rollback on user metrics.
Show answer
A layer-4 balancer picks a backend per connection, and gRPC runs many requests over one long-lived HTTP/2 connection, so each client sticks to one pod for its whole connection life. More replicas do not help. The fix is per-request balancing: an L7 proxy, a client-side balancer with service discovery, or a maximum connection age so clients re-connect and spread. Least-outstanding-requests helps when request cost varies. See load balancing and proxies and gateways.
Follow-ups:
- What does L7 cost? Added latency, certificate custody, and a stateful hop in the path.
- How does the client IP survive? Through
X-Forwarded-Foror the PROXY protocol, and the backend should trust it only from known proxies. - How do you tell it is connection stickiness? Compare per-connection counts and request rates per backend against the number of clients.
Show answer
For waiting that is not compute. A classic case is an origin connection-pool limit that was cut: with 8 connections at 80 ms each the pool serves about 100 requests per second, below 120 offered, so requests queue for a connection while CPU stays normal. Look at time spent waiting to get a connection, not origin execution time, and fetch the recent config diff. Roll back on one group first rather than raising every limit. See timeouts, retries and backoff and debugging by layer.
Follow-ups:
- Where does Little's Law come in? Connections needed equals request rate times service time, so a limit below that queues.
- Why compare healthy and failing paths? It holds all variables constant except the change, which points at the cause.
- What is the prevention item? Progressive config rollout and alerts on pool wait time.
Show answer
Outside the request handler, in the network setup. Subtract the curl -w fields: a time_connect that is whole seconds larger than time_namelookup, with one round trip on top, means the SYN was dropped and retransmitted (the first retransmit waits at least a second). Causes include listen-queue overflow and a full conntrack table. The application never sees those, so use ss -s, nstat and a black-box prober outside the network. See debugging by layer and TCP retransmission and timers.
Follow-ups:
- Why are the
curl -wtimes cumulative? Each is measured from the start, so per-phase time is the difference of consecutive values. - How do you join edge and app timing? By a correlation ID in both logs, and
Server-Timingheaders for the app's share. - How does staff-level differ? It adds an external prober and alerts on SYN-backlog counters, because the app cannot see this failure.
dig +trace works, the link looks fine, and the site is down. What next?seniorShow answer
Ping and dig +trace only prove ICMP reachability and public DNS. Go up the stack and prove each layer separately: curl --resolve host:443:IP to take DNS out of the equation, nc -vz to test the port, openssl s_client -servername to test the handshake, then curl -v for the HTTP response. Compare the stub with dig, since the system resolver may be failing where dig succeeds, and compare a working and a failing client. See debugging by layer and failure lab.
Follow-ups:
- Why use
--resolve? It proves compute, load balancer and TLS are healthy and isolates name resolution. - Why can
digand the browser disagree?digbypasses the stub and its caches, and the browser may use its own resolver. - Which result sends you where? Refused means a reachable host with no listener; silence means a drop; a handshake error means TLS or trust.
Show answer
BGP was a symptom. A maintenance command meant to assess backbone capacity took down all backbone connections, and an audit-tool bug failed to stop it. Facebook's DNS servers withdraw their own BGP advertisements when they cannot reach the data centres, so the DNS servers kept running but became unreachable. Resolvers then returned SERVFAIL and retried, and query load rose roughly 30x elsewhere. Recovery was slow because internal tools and physical access depended on the same failed network. See BGP basics and DNS.
Follow-ups:
- What is the lesson about health checks? Logic that withdraws routes on a failed check can turn a partial failure into a total one.
- How do you tell DNS is the cause or the first symptom? Compare several public resolvers and check route visibility with RIPE RIS or Cloudflare Radar.
- What about out-of-band access? Keep a path to the network that does not depend on the network being fixed.
Show answer
Use more than one independent authoritative DNS provider, with anycast on each, and set TTLs so cached answers outlast an outage. The October 2016 Dyn attack, a Mirai botnet DDoS against a single managed DNS provider, took down many large sites, and recursive-resolver retries amplified traffic roughly 10 to 20x. Heroku reported that its own response was slowed because the .com delegation TTL is 48 hours and cannot be changed, so moving providers could take up to that long, and it raised record TTLs and planned for multiple providers. See DNS and global traffic steering.
Follow-ups:
- Why do long TTLs help here but hurt elsewhere? They ride out provider outages but slow down migrations, so you pick by which risk you carry.
- What makes the storm worse? Retries at every layer, which is why failures are cached and clients back off.
- What if DNS-based failover is not allowed? Use anycast, client-side steering and retries across several endpoints.
Show answer
The DST Root CA X3 cross-signature expired. Servers sent the longer chain for old-Android compatibility, and Android ignores trust-anchor expiry, so those devices kept working. OpenSSL 1.0.x clients picked the expired path even though ISRG Root X1 was trusted, so they rejected the chain. API clients, IoT devices and older PHP builds failed. Fixes were serving the shorter alternate chain, upgrading OpenSSL to 1.1.0 or later, removing the expired root, or using -trusted_first. The lesson is that a valid certificate is client-dependent. See certificates and PKI.
Follow-ups:
- Why do
curland browsers disagree? Different trust stores and path-building rules. - What would have caught it? Testing against old client versions before the expiry date.
- What is the general rule? Treat trust-store age as a dependency you monitor.
Show answer
A latent race between a delayed DNS automation component and another one's cleanup deleted the plan, leaving an empty DNS record for the regional DynamoDB endpoint. DynamoDB errors ran from late on 19 October to early on 20 October (Pacific time), and dependent services such as EC2 launches, load-balancer health-check failover and Lambda were hit afterwards. The DNS failure was the first symptom of automation that could delete its own safety net, and recovery overloaded itself with a thundering herd. Dependency graphs and staged recovery are the takeaways. See DNS and timeouts, retries and backoff.
Follow-ups:
- What is a thundering herd on recovery? Every dependent retries at once as service returns, which can cause a second outage.
- What guards would you add? Safety checks so automation cannot apply an empty or stale plan.
- Why did unrelated services fail? They depended on the endpoint, directly or through control planes.
Show answer
In November 2025 a database permissions change made a Bot Management feature-file query return duplicate rows, doubling the file. The proxy preallocated space for 200 features (normal use is about 60), hit the limit and panicked, returning 5xx. Errors fluctuated every five minutes as good and bad files alternated, which resembled an attack. The lessons are to treat internally generated config as untrusted input, keep kill switches, fail safe when limits are hit, and be able to roll back data and not only code. See rate limiting and load shedding.
Follow-ups:
- Why did the intermittent pattern mislead? Alternating good and bad files looked like an external flood coming and going.
- What does fail-safe mean here? On overflow, keep serving the last good config rather than crash.
- How do you tell an attack from an internal bug? Compare traffic volume and sources against error rate, and check what changed recently.
Fun facts
- The speed of light in fibre sets a hard floor: about 5 microseconds per kilometre, so New York to Sydney cannot be under roughly 160 ms round trip.
- There are 13 named root server identities, A through M, but each is served by many anycast instances worldwide; root-servers.org lists the live count.
- A cold TCP connection can send about 14.6 KB in its first flight (10 segments of 1,460 bytes), which is why "keep critical HTML small" is common web performance advice.
- The fragment after
#is the one part of a URL that is never sent over the network. - The
Hostheader exists because HTTP/1.1 allowed many websites on one IP, and SNI in TLS exists for the same reason one layer down.
Cheat sheet
- DNS + 3 RTT - cold HTTPS over TCP and TLS 1.3 to the first byte
- DNS + 4 RTT - the same with TLS 1.2
- DNS + 2 RTT - HTTP/3 first contact; 1 RTT with 0-RTT or a reused connection
- 0 RTT - fresh cache hit in the browser
- 14,600 bytes - initial window, 10 segments x 1,460 (RFC 6928)
- 160 ms - best-case round trip over 16,000 km of fibre
- 0.8 s - web.dev guidance for a good time to first byte
- about 127 s - default Linux SYN retry give-up time (tcp_syn_retries = 6)
See the latency and capacity numbers reference for the wider table.