
Explainer: What Happens When You Type a URL and Press Enter?
Press Enter and something appears. Between the keystroke and the first pixel, your browser has to answer a short chain of questions in order: where does this name live, can I reach it, who am I actually talking to, what do I want from them, and what do I do with what comes back? Most of it happens in tens or hundreds of milliseconds, in parallel, on machines you will never see. Break that chain apart and you have a mental model that explains almost any slow page.
Before anything leaves the machine
A URL is not one thing. https://threadstack.co.uk/architecture/dns?page=2 carries a scheme, a host, a path and a query string, and the browser splits them before doing anything else. Then it looks in its own HTTP cache: a memory cache for the current session, a disk cache for anything older. The lookup key is the request method plus the URL, adjusted by any response headers that said the content varies by encoding or by cookie.
If a valid cached copy exists, you are done — the page renders from disk. If the copy is stale but revalidatable, the browser sends a conditional request with If-None-Match or If-Modified-Since, and the server may reply "304 Not Modified", which is headers and no body.
A couple of other checks happen here too. A registered service worker can intercept the request entirely and serve it without the network. And if the host is on the HSTS preload list, or has previously sent a Strict-Transport-Security header, the browser upgrades http:// to https:// before it does anything else.
DNS: turning a name into an address
Computers route by IP address, not by name, so something has to translate. The browser checks its own DNS cache, then hands the name to the operating system resolver, which usually forwards it to a recursive resolver — your ISP's, your router's, or a public one. If the answer is not already cached, the recursive resolver walks the hierarchy:
- The root servers, which point to the right top-level domain.
- The TLD servers for .uk, which point to the nameservers for the domain.
- The authoritative nameservers for threadstack.co.uk, which hold the actual records.
Records come in flavours. An A record gives an IPv4 address, AAAA gives IPv6, CNAME says "this name is really that name", and MX handles mail. Every answer carries a TTL — the number of seconds it may be cached. A five-minute TTL means changes take effect quickly but resolvers ask more often; a 24-hour TTL does the opposite. More outages live here than people expect, and no amount of server tuning fixes slow DNS.
Opening a connection: TCP, then TLS
With an IP address in hand, the browser opens a TCP connection to port 443. That starts with the three-way handshake: SYN, SYN-ACK, ACK. That is one full round trip before a single byte of HTTP can be sent. On decent broadband it costs a few milliseconds; on a poor mobile link it can cost a good deal more.
Then TLS takes over, and it is not free either.
What the TLS handshake actually does
- The client sends a ClientHello listing supported TLS versions, cipher suites and the server name it wants (SNI).
- The server responds with its certificate and chosen parameters; the browser validates the chain, the expiry date and the hostname.
- The two sides agree on a shared key, usually via ephemeral Diffie-Hellman, so the session key never travels over the wire.
- Both sides confirm with a Finished message, and encrypted application data can flow.
TLS 1.2 needs two round trips before the first request; TLS 1.3 cuts that to one, and a returning visitor with a valid session ticket can sometimes send data on the first flight. HTTP/3 goes further by running over QUIC rather than TCP, folding the transport and TLS handshakes together and removing the head-of-line blocking that comes with ordered TCP streams.
The request itself
Now the browser can speak HTTP. A request is a method, a path and headers. GET asks for a resource; POST sends a body, usually a form or a JSON payload. Headers tell the server what the browser can handle — Accept-Encoding: gzip, br means compressed responses are welcome — and what it already knows, through cookies and conditional headers.
Cookies deserve a mention. Every cookie matching the domain and path is attached to every request, so a bloated cookie jar sends kilobytes of headers before the server has done anything useful. Narrow cookie paths, plus HttpOnly, Secure and SameSite flags, are a small change with a real effect.
The server side of the fence
The request rarely lands directly on application code. In a typical setup it hits a CDN edge first. A cache hit is served from somewhere near you and the journey ends there. A miss means the edge forwards the request to an origin, often through a load balancer and a reverse proxy such as nginx or Caddy, which terminates TLS, applies rate limits and routes by host or path.
Behind that, the application works: authenticating the session, reading from a database or an in-memory cache, rendering HTML or serialising JSON. The response returns with a status code — 200 for success, 301 or 302 for redirects, 404 for a missing path, 500 for a broken server — plus headers describing content type, encoding, caching policy and any cookies to set. A redirect chain is worth watching for: each hop is a fresh round trip, and three hops on a mobile connection is noticeable.
Back in the browser: bytes to pixels
HTML arrives as a stream and is parsed into the DOM as it goes. CSS is fetched in parallel but blocks rendering: nothing is painted until the CSSOM is built, because a flash of unstyled content is worse than a short wait. JavaScript is messier — a plain script tag pauses parsing while it downloads and executes, which is why defer and async exist.
Once the DOM and CSSOM are ready, they combine into a render tree. Layout decides where each box sits, paint fills in the pixels, and the compositor stitches the layers together. Images, fonts and lazy-loaded content trickle in afterwards. A single-page framework may then spend further time hydrating — running the JavaScript that makes the markup interactive — during which clicks do nothing at all.
When a page feels slow, check the layers in order
- Browser cache: do a hard reload. Does the problem persist?
- DNS: is lookup time high in the network panel? Check TTLs and your resolver.
- Connection and TLS: a long wait before the first byte points at handshakes, certificate problems or a distant origin.
- Server: look at response time and status codes, including redirect chains and slow database calls.
- Rendering: large CSS bundles, render-blocking scripts and web fonts are the usual culprits.
The network panel in your browser's developer tools shows all of this in one place, sorted by the order things actually happened. Read it once with this sequence in mind and "the website is slow" becomes a specific question with a specific answer.
Photo: Firmbee / Pixabay
Designing Backpressure into Event-Driven Systems
Queues, rate limits and load shedding are the three levers that stop a busy producer overwhelming a slower...
Debugging Race Conditions with ThreadSanitizer: A Practical Walkthrough
ThreadSanitizer catches data races that only appear under load. Here is how to build with it, read its...




