SevyDevy

Guide · Backend

Networking from First Principles: What Happens When You Type a URL

15 min readUpdated By Saket Bhatnagar

Researched and drafted with AI, reviewed and edited by Saket Bhatnagar.

In short

  • When you type a URL, the browser parses it, upgrades it to HTTPS if HSTS says so, resolves the hostname to an IP through a chain of caches and DNS servers, opens a TCP connection, runs a TLS handshake, sends an HTTP request, and renders the HTML that comes back.
  • DNS resolution goes from your OS stub resolver to a recursive resolver, which (on a cache miss) asks a root server, then a TLD server like .com, then the domain's authoritative server, caching every answer for its TTL.
  • Over TCP with TLS 1.3, a brand new connection costs about two round trips before the request is even sent: one for the TCP handshake and one for the TLS handshake. HTTP/3 over QUIC folds both into a single round trip.
  • HTTP/2 multiplexes many requests over one TCP connection but still suffers TCP head-of-line blocking on packet loss; HTTP/3 fixes this by running independent streams over QUIC on UDP.
  • In production, the request usually lands on a CDN edge first; a cache hit is answered locally, while a miss travels to a load balancer, then app servers, caches and databases at the origin.
  • Distance dominates latency: with a 250 ms round trip from Bengaluru to a US-East origin, a cold HTTPS request takes close to a second before the first byte, while a nearby Indian edge can answer the same request in roughly 100 ms.

'What happens when you type a URL and press Enter?' is probably the most asked networking question in software interviews. Freshers get it in campus rounds. Senior engineers get it too, except the interviewer keeps saying 'go deeper' until you hit the edge of what you know.

The question is popular because it's a map of the whole stack. A good answer touches browsers, operating systems, DNS, transport protocols, cryptography, CDNs, load balancers, servers and rendering. This post walks one request from the address bar to pixels on screen, with the numbers that matter, so you can answer it at any depth. It's part of the Engineering Foundations series and pairs well with Backend Engineering from First Principles, which picks up where the request reaches your code.

What actually happens when you type a URL?

In one line: the browser turns the name into an IP address, opens a secure connection to that address, asks for a resource over HTTP, and renders what it gets back. Everything else is detail about how each of those steps is made fast and safe.

The detail matters because each step costs time, and most of that time is round trips. A round trip time (RTT) is how long it takes for a packet to go from your machine to a server and for the reply to come back. You can't make light travel faster through fibre, so most of web performance engineering is about doing fewer round trips or making each one shorter by moving servers closer to users.

The full path of one HTTPS request

DNS happens first and only returns an address; the real request goes to the CDN edge. Only cache misses travel on to the load balancer, app servers, cache and database at the origin.

Diagram connections:

  • Browser to DNS resolver (1. resolve name)
  • Browser to CDN edge (nearby PoP) (2. TCP + TLS + GET)
  • CDN edge (nearby PoP) to Load balancer (3. cache miss only)
  • Load balancer to App server A (healthy target)
  • Load balancer to App server B (healthy target)
  • App server A to Redis cache (read-through)
  • App server B to Redis cache (read-through)
  • App server A to Primary database (on miss / writes)
  • App server B to Primary database (on miss / writes)
  • Browser: Parses URL, checks HSTS and its own caches
  • DNS resolver: Turns www.example.com into an edge IP
  • CDN edge (nearby PoP): Terminates TLS, serves cache hits
  • Load balancer: L7: routes by host, path, header
  • App server A: Auth, business logic, rendering
  • App server B: Same code, another instance
  • Redis cache: Hot reads in under a millisecond
  • Primary database: Source of truth on a cache miss

How does the browser parse the URL, and where does HSTS fit in?

First the browser decides whether you typed a URL or a search query. 'example.com/cart' looks like a URL; 'cheap flights to goa' goes to your search engine. If it's a URL, the browser splits it into scheme (https), host (www.example.com), optional port, path (/cart), query string and fragment. The fragment after # never leaves the browser.

Non-ASCII hostnames are converted to their punycode form (the xn-- names) because DNS only deals in ASCII. If you typed a bare domain with no scheme, most modern browsers try https:// first.

Then comes HSTS. HTTP Strict Transport Security is a response header that tells the browser 'only ever talk to this domain over HTTPS, for the next max-age seconds'. If the browser has an HSTS entry for the host, it rewrites http:// to https:// internally before any packet leaves. In Chrome DevTools this shows up as a 307 Internal Redirect, which is a nice detail to mention in an interview.

HSTS has a known gap: the browser only learns the policy after one successful HTTPS visit, so the very first plain-HTTP request can be intercepted. The fix is the preload list, a list of domains compiled into browsers. To qualify, the header needs a max-age of at least one year, includeSubDomains and the preload directive.

http
HTTP/1.1 200 OK
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Which caches are checked before a DNS query leaves your machine?

Several, and a lot of requests never reach the network at all. Before thinking about DNS, the browser checks whether it can skip the request entirely or reuse something it already has.

  • HTTP cache: if the resource was cached with a Cache-Control max-age that hasn't expired, the browser serves it from memory or disk with zero network cost. Service workers can also intercept the request here.
  • Existing connections: if there's already an open, healthy connection to that origin, the browser reuses it and skips DNS, TCP and TLS. This is why the second page load on a site feels faster.
  • Browser DNS cache: Chrome keeps its own host cache (you can inspect and clear it at chrome://net-internals/#dns).
  • OS resolver: the operating system checks the hosts file and its own cache (systemd-resolved on many Linux distros, mDNSResponder on macOS). The part of the OS that does this is called the stub resolver.
  • Home router and ISP: your router often caches too, and the ISP's recursive resolver has a large shared cache that many users warm up for you.

If the browser has Secure DNS turned on, it sends queries to a DNS-over-HTTPS resolver instead of the OS resolver, which hides the names you look up from your local network. Modern browsers also ask for more than one record type: A for IPv4, AAAA for IPv6, and often the HTTPS record, which can advertise that the server speaks HTTP/3 before any connection is opened.

How does DNS resolution work, step by step?

DNS resolution is a chain of referrals. The stub resolver asks one recursive resolver, and on a cache miss that resolver walks down the hierarchy: root servers point it to the TLD servers, TLD servers point it to the domain's authoritative servers, and the authoritative server gives the final answer.

DNS resolution from stub to authoritative

The stub resolver makes one recursive query; the recursive resolver does all the walking. Root and TLD only hand out referrals, and every answer is cached for its TTL so most lookups stop at the first or second box.

Diagram connections:

  • Browser to OS stub resolver (getaddrinfo())
  • OS stub resolver to Recursive resolver (recursive query)
  • Recursive resolver to Root server (.) (who runs .com?)
  • Recursive resolver to .com TLD server (who runs example.com?)
  • Recursive resolver to Authoritative NS (A for www.example.com?)
  • Browser: Checks its own host cache first
  • OS stub resolver: hosts file, OS cache, then forwards
  • Recursive resolver: ISP, 1.1.1.1, 8.8.8.8; big shared cache
  • Root server (.): 13 named identities, anycast worldwide
  • .com TLD server: Knows the NS records for example.com
  • Authoritative NS: Holds the real A / AAAA / CNAME records
  1. Stub to recursive

    Your OS sends a query for www.example.com to the configured recursive resolver, usually over UDP port 53 (or encrypted over DoH or DoT). It asks for a complete answer and waits.

  2. Recursive to root

    If nothing is cached, the resolver asks a root server. The root doesn't know the IP; it replies with a referral listing the .com TLD nameservers.

  3. Recursive to TLD

    The resolver asks a .com server, which replies with another referral: the nameservers for example.com, often with their IPs attached as glue records.

  4. Recursive to authoritative

    The authoritative server returns the actual record. For a site on a CDN this is often a CNAME to the CDN's hostname, which triggers another short lookup chain before you get an IP.

  5. Cache and return

    The resolver caches every answer along the way for its TTL and returns the final IP to your OS, which hands it to the browser.

About root servers: there are 13 named root server identities, a.root-servers.net through m.root-servers.net, but that doesn't mean 13 machines. Each identity is served by many anycast instances spread around the world, roughly two thousand in total, so a query from Bengaluru is answered by an instance close to Bengaluru.

TTLs: the knob that trades freshness for speed

A DNS TTL is the number of seconds a resolver may cache a record before asking again. Referrals for TLDs are cached for a long time, often a day or more, which is why resolvers almost never talk to root servers for popular names. Your own A record's TTL is your call.

A long TTL (say an hour) means fewer lookups and faster page loads, but a bad record lingers for an hour after you fix it. A short TTL (30 to 60 seconds) lets you fail over quickly, at the cost of more queries and more cold lookups. The standard trick before a migration: drop the TTL to 60 seconds a day ahead, switch the record, then raise it again. Also remember that some resolvers clamp or ignore very low TTLs, so never design failover that depends on a 5-second TTL being honoured everywhere.

bash
# Walk the delegation chain yourself: root -> .com -> authoritative
dig +trace www.example.com

# See the TTL your resolver is counting down
dig www.example.com A +noall +answer

# Ask for the HTTPS record (alpn, IP hints)
dig www.example.com HTTPS +short

Why does the TCP handshake cost a full round trip?

Because both sides must agree on starting sequence numbers before any data can flow reliably. The client sends SYN with its initial sequence number, the server answers SYN-ACK with its own, and the client sends ACK. The client can put the HTTP or TLS bytes right after that ACK, so the cost before the first useful byte is one full RTT.

The handshake also negotiates options: maximum segment size, window scaling and selective acknowledgements. Random initial sequence numbers make it hard for an off-path attacker to inject packets into your connection.

One more hidden cost is slow start. A new TCP connection doesn't know how much bandwidth the path has, so the sender starts with a small congestion window (commonly 10 segments, about 14 KB) and roughly doubles it every round trip. On a long, cold connection, a 100 KB HTML page needs a few extra round trips just to ramp up. This is the real reason connection reuse and keep-alive matter so much.

How does the TLS 1.3 handshake work, and what is the catch with 0-RTT?

TLS 1.3 needs one round trip. The client's first message, ClientHello, already includes a key share (its half of a Diffie-Hellman exchange), the hostname in SNI, and the protocols it supports through ALPN (for example h2 and http/1.1). The server replies in one flight with ServerHello and its key share, then its certificate, a signature proving it owns the certificate's key, and Finished, all encrypted after ServerHello. The client checks the certificate, sends its own Finished and can send the HTTP request in the same flight.

TLS 1.2 needed two round trips for a full handshake, so this one change saves a whole RTT on every new connection. If the client guesses the wrong key exchange group, the server answers with HelloRetryRequest and you pay an extra round trip, which is why servers and CDNs care about matching what browsers send first.

TCP + TLS 1.3 vs QUIC, flight by flight

Top path: TCP needs a round trip before TLS can start, so the GET leaves after two RTTs. Bottom path: QUIC carries the TLS 1.3 handshake in its first packets, so the GET leaves after one RTT.

Diagram connections:

  • SYN to SYN-ACK (RTT 1)
  • SYN-ACK to ACK + ClientHello (handshake done)
  • ACK + ClientHello to ServerHello ... Finished (RTT 2)
  • ServerHello ... Finished to Finished + GET / (keys ready)
  • QUIC Initial + ClientHello to QUIC ServerHello ... Fin (RTT 1)
  • QUIC ServerHello ... Fin to Finished + GET / (keys ready)
  • Finished + GET / to 200 OK + HTML (RTT 3 (TCP) / 2 (QUIC))
  • SYN: TCP: client picks a sequence number
  • SYN-ACK: End of RTT 1 for TCP
  • ACK + ClientHello: key_share, SNI, ALPN h2
  • ServerHello ... Finished: Cert, CertificateVerify; end of RTT 2
  • QUIC Initial + ClientHello: UDP; transport and TLS together
  • QUIC ServerHello ... Fin: End of RTT 1 for QUIC
  • Finished + GET /: First HTTP request bytes leave
  • 200 OK + HTML: Another RTT plus server time

0-RTT: faster, but replayable

If you've connected to the server before, TLS 1.3 can resume with a pre-shared key and let the client send early data in its very first flight. That's 0-RTT: the request leaves with the ClientHello. The catch, spelled out in RFC 8446, is that early data has weaker replay protection than normal traffic and isn't forward secret.

Replay means an attacker who captured that first flight can send it again, and the server may process it twice. For a GET of a product page, that's harmless. For 'POST /upi/pay amount=500', it's a double payment. So the rule is simple: only allow idempotent, safe requests in 0-RTT. Servers can reject early data, and RFC 8470 defines the 425 Too Early status for exactly that case.

HTTP/1.1 vs HTTP/2 vs HTTP/3: what changed and why?

Each version fixed the biggest bottleneck of the one before it. HTTP/1.1 can only have one request in flight per connection, so browsers open several connections per host (Chrome's limit is 6). HTTP/2 multiplexes many requests over one TCP connection. HTTP/3 moves to QUIC so that one lost packet doesn't stall every stream.

Head-of-line blocking is when one stuck item at the front of a queue holds up everything behind it. HTTP/2 removed it at the HTTP layer but not at the TCP layer: TCP delivers bytes strictly in order, so if one packet carrying part of a CSS file is lost, the JavaScript and image bytes behind it wait in the kernel until the retransmission arrives. On lossy mobile networks this can make HTTP/2 behave worse than several HTTP/1.1 connections. QUIC tracks loss per stream, so only the stream that lost data waits.

HTTP/1.1 vs HTTP/2 vs HTTP/3 at a glance
AspectHTTP/1.1HTTP/2HTTP/3
TransportTCPTCPQUIC over UDP
EncryptionOptional (TLS on top)TLS in practice (browsers require it)TLS 1.3 built into QUIC, always on
Requests per connectionOne at a time; browsers open ~6 connections per hostMany multiplexed streams on one connectionMany independent streams on one connection
Head-of-line blockingYes, per connectionFixed at HTTP layer, still present in TCPRemoved: loss stalls only the affected stream
Header formatPlain text, repeated every requestBinary frames, HPACK compressionBinary frames, QPACK compression
New connection cost (with TLS 1.3)2 RTT before request2 RTT before request1 RTT (0-RTT on resumption)
Network change (Wi-Fi to 4G)Connection breaksConnection breaksSurvives via connection IDs
How the browser picks itDefault fallbackALPN during TLS handshakeAlt-Svc header or HTTPS DNS record

Two practical notes. First, a browser usually can't use HTTP/3 on the very first connection unless the HTTPS DNS record advertises it; otherwise it connects over HTTP/2, sees an Alt-Svc header, and uses QUIC next time. Second, some corporate networks block UDP, so browsers race or fall back to TCP. HTTP/3 is an upgrade path, not a replacement you can rely on everywhere.

What do the CDN and the load balancer do with your request?

For most real sites, the IP that DNS returns belongs to a CDN, not to your server. The CDN routes you to a nearby point of presence (PoP), either through anycast (the same IP announced from many locations) or by returning a different IP based on your resolver's location. The edge terminates TCP and TLS close to you, which is where the big latency win comes from.

The edge then builds a cache key (usually host, path and selected query parameters) and looks it up. On a hit, it answers immediately; headers like cf-cache-status: HIT on Cloudflare or X-Cache: Hit from cloudfront on CloudFront tell you this happened. On a miss, it fetches from the origin, often through a regional mid-tier cache, over connections it keeps warm, and stores the response if Cache-Control allows. Personalised responses (your Swiggy cart, your bank balance) are marked private or no-store and always go to origin.

At the origin, a load balancer spreads requests across healthy app servers. The key distinction interviewers like is layer 4 vs layer 7.

Layer 4 vs layer 7 load balancing
AspectL4 load balancerL7 load balancer
SeesIP addresses, ports, TCP/UDP flowsFull HTTP: method, path, headers, cookies
TLSUsually passes it through untouchedUsually terminates it to read the request
Routing optionsHash on connection tuple, round robin/api to one pool, /static to another, canary by header
Cost per requestVery low, can handle huge connection countsHigher: parses every request
Extra featuresFew; good for any TCP or UDP protocolRetries, rate limits, auth, header injection, WAF
ExamplesAWS NLB, Linux IPVS, Maglev-style balancersAWS ALB, Nginx, Envoy, HAProxy in HTTP mode

Big systems often stack both: an L4 layer spreads raw connections across a fleet of L7 proxies, which then make smart per-request decisions. Both kinds run health checks and take failing servers out of rotation, which is what lets you deploy without downtime.

What happens on the server and on the way back?

The request finally reaches your code. A reverse proxy or framework parses it, middleware authenticates the user from a cookie or token, the router picks a handler, and the handler reads from a cache like Redis or falls through to the database. It then builds the response: status code, headers such as Content-Type, Cache-Control and Set-Cookie, and a body compressed with gzip or Brotli if the client said it accepts them.

The response retraces the path: app server to load balancer to CDN edge (which may cache it) to the browser. The connection stays open with keep-alive so the next request skips the handshakes. If you want the depth on what happens inside the server, from validation to retries and idempotency, that's the subject of the companion post.

How does the browser turn the response into pixels?

This is the critical rendering path. The browser parses HTML into the DOM incrementally as bytes arrive. CSS is render-blocking: the browser won't paint until it has built the CSSOM. A plain script tag is parser-blocking: HTML parsing pauses while it downloads and runs, which is why defer and async exist.

Once the DOM and CSSOM are ready, the browser combines them into a render tree (only visible elements), runs layout to compute sizes and positions, paints pixels and composites layers. Each new image, font or script the HTML references kicks off its own request, which usually reuses the open connection and skips straight to the HTTP step. A good rule: keep critical CSS small, defer non-critical JavaScript, and make sure the first 14 KB or so of HTML contains something useful to render.

Latency budget: Bengaluru user, US-East origin vs an Indian edge

Numbers make this concrete. Azure publishes a median round trip of about 220 ms between its South India and East US regions on its own backbone. Add last-mile latency for a home broadband or 4G user and 250 ms is a fair round number for Bengaluru to US-East. A CDN PoP in India might be 20 ms away. Assume DNS takes 40 ms and the app server needs 50 ms to build the page. These are illustrative assumptions, not measurements of any particular site.

Time to first byte for a cold HTTPS request (TCP + TLS 1.3), illustrative numbers
StepDirect to US-East originIndian edge, cache hitIndian edge, cache miss
DNS lookup40 ms40 ms40 ms
TCP handshake (1 RTT)250 ms20 ms20 ms
TLS 1.3 handshake (1 RTT)250 ms20 ms20 ms
Request to first byte250 ms + 50 ms server20 ms + ~5 ms edge20 ms + 220 ms to origin + 50 ms server
Total TTFB~840 ms~105 ms~370 ms

Three lessons fall out. Handshakes are where distance hurts most, because they multiply the RTT; moving TLS termination to the edge saves two long round trips even on a cache miss, since the edge reuses warm connections to the origin. A cache hit turns an 840 ms request into a 100 ms one. And with HTTP/3 to the edge, the TCP and TLS rows merge, saving one more short RTT.

This is why apps serving India (think Hotstar during a cricket final, or Flipkart during Big Billion Days) push static assets and cacheable API responses to Indian PoPs, and why a startup running only in us-east-1 feels slow to its Indian users even when the server code is fast.

bash
# Measure each phase of a real request from your machine
curl -so /dev/null https://www.example.com \
  -w 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n'

The timings curl prints are cumulative from the start, so subtract neighbours to get each phase. Run it against a site hosted only in the US and one served from an Indian edge, and the table above stops being theory.

How to answer this in an interview: 2 minutes vs 10 minutes

Interviewers use this question to see if you can structure a big answer and go deep on demand. Start with the skeleton, then ask which part they want expanded. Don't recite everything you know in one breath.

The 2-minute version

  • Browser parses the URL, applies HSTS, checks its HTTP cache and open connections.
  • DNS: browser and OS caches, then a recursive resolver that walks root, TLD and authoritative servers, caching by TTL.
  • TCP handshake (1 RTT), then TLS 1.3 handshake (1 RTT) with certificate validation; HTTP/3 over QUIC combines them.
  • HTTP request goes to a CDN edge; hit returns from cache, miss goes through a load balancer to app servers, cache and database.
  • Response comes back, connection is kept alive, browser builds DOM and CSSOM, lays out and paints.

The 10-minute version

Same skeleton, but at each step add one 'why' and one trade-off. Explain TTL as freshness vs lookups. Explain why TCP costs an RTT and how slow start hurts cold connections. Walk through the TLS 1.3 flights and the 0-RTT replay risk. Compare HTTP/2 and HTTP/3 head-of-line blocking. Contrast L4 and L7 load balancing. Then close with a latency budget like the one above, because putting numbers on the answer is what separates senior candidates.

  • Mistake: saying every lookup goes to a root server. With caching, almost none do.
  • Mistake: saying there are 13 root servers. There are 13 identities served by many anycast instances.
  • Mistake: doing TLS before TCP, or forgetting that TLS 1.2 took two round trips and TLS 1.3 takes one.
  • Mistake: claiming HTTP/2 solved head-of-line blocking. It moved the problem down into TCP.
  • Mistake: treating the load balancer as one box. In practice it's a redundant fleet, often L4 in front of L7.

Questions people ask

What happens when you type google.com in a browser?
The browser upgrades the address to HTTPS, resolves google.com to a nearby Google edge IP using cached or fresh DNS answers, opens a connection (usually HTTP/3 over QUIC or HTTP/2 over TCP with TLS 1.3), sends a GET request, and renders the HTML, CSS and JavaScript that come back. Google's edge is close to most users, so the handshakes take only a few milliseconds.
Does DNS use TCP or UDP?
DNS mostly uses UDP on port 53 because a single small question and answer fits in one packet with no handshake. It switches to TCP when a response is too large for UDP and for zone transfers between servers. Encrypted options like DNS over HTTPS and DNS over TLS run over TCP, or over QUIC for DNS over HTTP/3.
Why is HTTP/3 faster than HTTP/2?
HTTP/3 is faster mainly on new connections and lossy networks. QUIC combines the transport and TLS 1.3 handshakes into one round trip instead of two, and it handles packet loss per stream, so one lost packet doesn't stall every request. It also survives network changes, such as switching from Wi-Fi to mobile data, using connection IDs. On a clean, warm connection the difference is small.
What is the difference between the TLS 1.2 and TLS 1.3 handshakes?
TLS 1.3 completes a full handshake in one round trip, while TLS 1.2 needs two. TLS 1.3 gets there by having the client send its key share in the first message, encrypting most of the handshake, and removing old insecure options like RSA key exchange. It also adds 0-RTT resumption, which is faster but replayable, so it should only carry idempotent requests.
What is the difference between a CDN and a load balancer?
A CDN brings content closer to users, while a load balancer spreads traffic across servers in one location. The CDN runs edge servers in many cities, terminates connections near the user and serves cached responses. The load balancer sits in front of your app servers at the origin, picks a healthy server for each connection or request, and handles failover. Most production sites use both.
How many root DNS servers are there?
There are 13 named root server identities, a.root-servers.net to m.root-servers.net, run by 12 independent operators. Each identity is served by many anycast instances worldwide, adding up to roughly two thousand servers, so queries reach a nearby copy. Resolvers rarely need them anyway, because TLD referrals are cached for long periods.
What is a good DNS TTL for a website?
For most stable sites, a TTL between 300 seconds and one hour is a sensible default. Longer TTLs mean fewer lookups and faster repeat visits but slower recovery from a bad record. Shorter TTLs, around 60 seconds, help during migrations and failover. Lower the TTL a day before planned changes, then raise it again once the new record is stable.

A good next step: run dig +trace and the curl timing command against three sites you use daily, one Indian, one global and one hosted only in the US, and explain the differences out loud. If you can do that, you can answer this question at any depth an interviewer asks for.

Sources and further reading

Practise this with Lala

Practise