Preface
In late 2024, I led my first technical interview. Until then, I had only shadowed calls, but never conducted one myself. To prepare, I reached out to experienced colleagues to learn their approaches, both in general and within the context of our company.
Each person had their own unique approach. Some favored a more traditional question-and-answer method. Others preferred a looser chat with open-ended questions to explore a candidate’s thinking process. However, Ondrej Sevcik shared with me a question which I found particularly fascinating:
“What happens when you type Google.com in your browser and press Enter?”
It’s deceptively simple. Yet, how you answer reveals a lot about your experience and specialization. A junior developer might mention a request being made and a page being rendered. A DevOps engineer could dive deep into TCP handshakes and load balancers. A front-end specialist might focus on the browser part, mentioning parsing, rendering, and paint cycles.
The beauty of this question lies in its depth. You can answer it in 30 seconds or 30 minutes, and both responses can be valid depending on the context.
Let’s break down this classic interview question together.
From Request To Response
We can break the journey from keystroke to rendered page into five phases:
flowchart
subgraph A["1. Pre-Request"]
direction LR
A1([Cache]) --> A2([HSTS]) --> A3([Service Worker]) --> A4([DNS Resolution])
end
subgraph B["2. Connection"]
direction LR
B1([TCP Handshake]) --> B2([TLS Handshake])
end
subgraph C["3. Request"]
C1([HTTP GET])
end
subgraph D["4. Response"]
direction LR
D1([Server Response]) --> D2([Redirects])
end
subgraph E["5. Rendering"]
direction LR
E1([Parsing]) --> E2([JavaScript]) --> E3([Layout & Paint])
end
A ---> B ---> C ---> D ---> E
That’s the big picture. We could go far more granular – each step hides layers of complexity – but this overview will serve us well. Now let’s dig into some details.
Pre-Request
Cache
Before your browser reaches out to the internet, it checks if it even needs to. Have we visited this page recently? Is there a fresh copy stored locally? If so, the journey might end right here – no network request needed at all.
But “fresh” is doing a lot of work in that sentence. Every cached resource comes with rules – usually via Cache-Control headers – that tell the browser how long it can trust the local copy. Some resources are cacheable for days, others for mere seconds.
What if the cache has expired? The browser doesn’t give up – it prepares a conditional request. Using headers like If-Modified-Since or If-None-Match, it essentially asks the server: “has this changed since last time?” If not, the server can respond with a tiny 304 Not Modified instead of re-sending the entire resource. The decision to try this optimization happens here, before any request is made.
HSTS
Simultaneously, the browser checks its HSTS preload list. This is a separate concern from caching – it’s about how to connect, not whether to connect. Certain domains are hardcoded to always use HTTPS. Google is on that list, so even if you typed http://google.com, the browser upgrades to HTTPS before any request leaves your machine.
What’s HSTS?
HTTP Strict Transport Security is a header servers send to say “only connect to me over HTTPS.” Browsers remember this and automatically upgrade future requests.
The preload list goes further – browsers ship with a hardcoded list of domains that must always use HTTPS, protecting even the very first visit. This prevents SSL stripping attacks, where an attacker intercepts the initial HTTP request before the browser learns about HTTPS requirements.
Notable preloaded domains include Google, Facebook, Twitter, PayPal, GitHub, and even entire TLDs like .gov. You can check any domain at hstspreload.org.
Service Worker
For modern Progressive Web Apps, there’s another gatekeeper: the service worker. This JavaScript running in the background can intercept requests and respond with cached data, synthetic responses, or decide to let the request through. It’s like having a programmable proxy inside your browser.
If a service worker handles the request, the journey might end here – your page renders from locally cached assets without touching the network. This is how PWAs work offline. But for our Google example, let’s assume we need fresh data.
With no shortcuts available, the real journey begins.
DNS Resolution
Your browser faces its first real challenge. It has no idea where google.com actually lives. Domain names are convenient for humans, but computers speak in IP addresses, so the browser needs to translate.
This translation happens through DNS – the phonebook of the internet. Your browser first checks its own memory – did we visit Google recently? If not, it asks the operating system. Still nothing? The request travels to your router, then to your ISP’s DNS resolver. In the worst case, the query bounces between root servers, TLD servers, and authoritative nameservers until finally, an IP address like 142.250.186.78 emerges from the void.
All of this happens in milliseconds, yet it’s often where latency hides.
Here’s where it gets interesting. That IP address might not point to the given website’s actual servers. For most services, DNS returns the address of a CDN edge server – a cache sitting geographically close to you, dramatically reducing latency. We’ll see how CDNs come into play again when the response arrives.
Connection
TCP Handshake
Armed with an IP address, your browser reaches out across the internet to Google’s server. But before any data can flow, both parties need to agree they’re ready to talk. This is the TCP handshake – a brief, polite introduction.
- Your browser sends a SYN packet
”Houston, I’d like to connect.” - Google’s server responds with SYN-ACK
”Acknowledged, I’m ready too.” - Your browser confirms with ACK
”Perfect, let’s begin.”
Three packets. Three confirmations. Now there’s a reliable channel between you and Google, one that guarantees data arrives in order and intact.
Of course, I’m glossing over a lot here. Those packets don’t magically teleport – they hop through routers, get their IP addresses resolved to MAC addresses, traverse undersea cables, and navigate the internet’s routing infrastructure. Each step along the way is its own story.
For most web developers, this layer is invisible, but network engineers could spend hours here.
TLS Handshake
But we’re not done with handshakes. Since we’re using HTTPS, another negotiation begins – this time for security. Your browser and Google’s server need to establish encrypted communication without anyone eavesdropping.
The TLS handshake is where cryptography enters the picture.
Your browser announces which encryption methods it supports. Google responds with its digital certificate – proof of identity signed by a trusted authority. Both sides then derive shared secret keys through mathematical magic, and from this point forward, everything between you and Google is encrypted.
Again, the details could fill a PhD thesis, but that’s not our focus here – especially since we’re finally so close to making the actual request.
Request
HTTP GET
Finally, your browser can ask for what you wanted: Google’s homepage. It sends an HTTP GET request through the encrypted tunnel – a simple message asking for the document at the root path.
But what does that message actually look like? At its core: a method (GET), a path (/), and an HTTP version. Surrounding that are headers – metadata about the request. Host: google.com tells the server which website you want (crucial when one server hosts many domains). User-Agent identifies your browser. Accept-Encoding advertises which compression formats you understand, like gzip or Brotli.
If you’re using HTTP/2 or HTTP/3, things get more efficient. Headers are compressed, and multiple requests can share a single connection – no more waiting for one resource before requesting the next. But the fundamental idea remains: your browser sends a request and waits for a response.
Response
Server Response
Google’s servers receive this request, and somewhere in their vast infrastructure, a response is assembled. Every response includes a status code – a three-digit number that tells the browser what happened. 200 means success. 404 means not found. 500 means something broke on the server. These codes shape how the browser handles what comes next.
But “Google’s servers” hides enormous complexity. Remember those CDN edge servers from earlier? If you’re requesting static assets – images, scripts, stylesheets – those might be served directly from the edge cache without ever reaching Google’s origin servers. For dynamic content, your request likely hits a load balancer first, which decides which of thousands of servers should handle it. That server might sit behind a reverse proxy. The application code runs, perhaps querying databases, aggregating data from microservices, rendering templates. The response gets compressed with gzip or Brotli before being sent back. Backend engineers could unpack this single paragraph into an entire architecture discussion.
Redirects
But wait! What if you typed google.com without the www?
Instead of a 200 OK, the server responds with a 301 Moved Permanently – a redirect. The response body is almost empty, but the Location header says: “The page you want is actually at www.google.com.”
Your browser follows the redirect. In the worst case – a redirect to a completely different domain – this means starting much of the process over: new DNS lookup, new TCP connection, new TLS handshake. For same-origin redirects, browsers are smarter; they can often reuse existing connections. Still, a redirect adds latency. It might double your connection time in relative terms – but when we’re talking about doubling 50ms to 100ms, the absolute penalty is barely noticeable to users.
What about that www?
The www prefix is a subdomain convention from the early web, used to distinguish web servers from other services like mail or ftp. Today it’s largely historical – many sites work with or without it.
Modern convention leans toward naked domains (example.com) for cleaner URLs. Some still use www for DNS flexibility, but most CDNs and hosting platforms have solved this limitation.
What’s my preference? Just check the URL of this page. ;)
With redirects resolved, the HTML finally flows back through the encrypted tunnel – carrying the structure of the page we’re about to see.
Rendering
The browser now holds raw HTML – a blueprint, not a picture. The rendering engine springs into action.
Parsing
First, it parses the HTML into a DOM tree – a structured representation of every element on the page. But HTML is just the beginning. As the parser encounters <link>, <script>, and <img> tags, it fires off additional requests for CSS, JavaScript, images, and fonts.
Simultaneously, the browser processes CSS into a CSSOM – the styling rules that determine how everything should look. These two trees merge into a render tree, filtering out invisible elements and mapping styles to content.
JavaScript
As usual, JavaScript complicates everything. 😅
When the parser hits a <script> tag, it typically pauses – the script might modify the DOM, so the browser waits for it to download and execute before continuing. This is why you’ll see defer and async attributes on script tags, or why scripts are placed at the bottom of the page. A poorly placed script can block rendering entirely, leaving users staring at a blank screen.
Layout & Paint
Then comes layout. The browser calculates exactly where every element should appear and how much space it needs. Finally, paint: pixels are drawn to the screen. For complex pages, the browser assembles compositing layers for smooth animations.
What started as a keystroke is now a fully rendered page.
Why This Question Matters
This question isn’t about memorizing steps. It’s about revealing how you think.
There’s no perfect answer. A front-end developer who spends five minutes on the rendering pipeline and glosses over TCP is just as valid as a backend engineer who does the opposite. The question adapts to whoever is answering it.
Closing Thoughts
The web is a remarkable stack of technologies, each layer building on the previous one. Understanding this stack – even at a high level – makes you a better engineer.
Next time you press Enter, take a moment to appreciate the orchestrated complexity happening in those few hundred milliseconds.
Further Read
After publication, my colleague Ivan Pesin shared with me the “What Happens When” repository that thoroughly examines this question. Definitely worth a read as it goes way more in depth on specific topics. I’m glad I wasn’t aware of it prior to publication, though. 😉
Interested in exploring specific topics? Here are some trusted sources:
- DNS & Networking
- How DNS Works – A fun comic explaining DNS step by step
- What is DNS? – Cloudflare’s comprehensive guide
- Security & HTTPS
- HSTS Preload List – Check if a domain is preloaded
- How HTTPS Works – Another comic-style explainer
- Transport Layer Security (TLS) – MDN’s technical reference
- HTTP
- HTTP Status Codes – MDN’s complete reference
- HTTP Overview – Understanding the protocol
- Performance & CDNs
- What is a CDN? – Cloudflare’s CDN explainer
- web.dev Performance – Google’s performance learning path
- Browser Rendering
- How Browsers Work – Deep dive into rendering engines
- Critical Rendering Path – MDN’s guide to browser rendering

No comments yet. Be the first to join the conversation!