In 30 seconds
When you open a website, your browser finds the server's address (DNS), opens a connection to it (TCP or QUIC), makes it private (TLS), asks for the page (HTTP) and then turns the answer into pixels. Each step takes milliseconds, and each one is a place where a site can be fast or slow, safe or broken. Knowing the chain is the base for every other web topic.
Why I use it
- I use this mental model every day: when a site is slow or down, I walk the chain step by step instead of guessing.
- Almost every production bug I meet sits at one link of this chain: a DNS record, a certificate, a proxy header, a cache or a render-blocking script.
- It lets me explain to clients, in plain words, why a CDN, HTTPS or caching is worth paying for.
- Frontend speed and backend speed only make sense together; this journey connects them.
How it works
01The big picture: a restaurant analogy
Think of visiting a website like ordering in a restaurant you have never been to. First you look up the address (DNS). Then you walk there and get a table (a TCP connection). You agree with the waiter on a private language so nobody else can listen in (TLS). You place your order from the menu (an HTTP request). The kitchen cooks (the server runs code and queries a database). The waiter brings the plate (the HTTP response), and you arrange it on the table and start eating (the browser parses and renders). A CDN is a branch of the restaurant near your house that already has popular dishes ready. Keep this picture in mind; every step below is one part of it.
- URL: https://example.com/products?page=2 = scheme + host + path + query.
- Client = the browser or app; server = the machine that answers.
- Latency (round-trip time) matters more than bandwidth for most pages.
02Step 1–3: DNS, TCP and TLS
The browser needs an IP address, not a name. It checks its own cache, the operating system, then asks a recursive resolver (from your ISP, 1.1.1.1 or 8.8.8.8). The resolver walks root servers, then the .com servers, then the domain's authoritative nameservers, and caches the answer for its TTL. With the IP, the browser opens a TCP connection using a three-way handshake (SYN, SYN-ACK, ACK) to port 443. Then TLS 1.3 runs: browser and server agree on keys and the server proves its identity with a certificate. TLS 1.3 needs one extra round trip; HTTP/3 merges transport and TLS into a single QUIC handshake over UDP. On a 100 ms mobile link these round trips are already 200–300 ms before any HTML arrives, which is why reused connections and nearby servers matter.
# See each phase of a real request with timings
curl -o /dev/null -s -w "dns: %{time_namelookup}s
tcp: %{time_connect}s
tls: %{time_appconnect}s
first byte: %{time_starttransfer}s
total: %{time_total}s
" https://example.com/
03Step 4–6: request, server, response
Over the secure connection the browser sends an HTTP request: a method (GET), a path, and headers such as Host, Accept-Language, cookies and caching hints. On the server side, a web server like nginx receives it. It may answer directly with a static file, or pass the request to an application (Laravel through PHP-FPM, a Node.js process) that runs business logic, reads a database or cache and builds HTML or JSON. The response comes back with a status code (200, 301, 404, 500), headers (Content-Type, Cache-Control, Set-Cookie) and a body, usually compressed with gzip or Brotli. Time to First Byte (TTFB) measures this whole round: network plus server work. Slow TTFB usually means slow queries, no caching, or a server far away from the user.
GET /products?page=2 HTTP/1.1
Host: example.com
Accept: text/html
Accept-Encoding: br, gzip
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: br
Cache-Control: public, max-age=60
04Step 7: the browser builds the page
The browser reads HTML as it streams in and builds the DOM, a tree of elements. When it finds CSS it downloads and parses it into the CSSOM; CSS is render-blocking because the browser will not paint unstyled content. Classic script tags block parsing too, unless they use defer or async. DOM and CSSOM combine into a render tree, then the browser computes layout (sizes and positions), paints pixels and composites layers on the GPU. Images, fonts and extra scripts load in parallel. JavaScript can change the DOM later, which can trigger layout again. Core Web Vitals measure the result: LCP (how fast the main content appears), INP (how fast the page reacts to input) and CLS (how much things jump around).
- Put CSS early, scripts with defer, and give images width and height.
- Preload the hero image and main font; lazy-load what is below the fold.
- Less JavaScript almost always means a faster, more responsive page.
05Where a CDN fits
A CDN (Content Delivery Network) such as Cloudflare, Fastly or CloudFront runs servers in hundreds of cities. When your DNS points to the CDN, the visitor's TLS handshake ends at the nearest edge server, often 10–30 ms away instead of 150 ms. The edge serves cached files (images, CSS, JS, sometimes whole HTML pages) directly, and only forwards cache misses to your origin server over a warm, reused connection. Many CDNs also add DDoS protection, a web application firewall and HTTP/3. The cost is one more layer to understand: caching rules, SSL settings between edge and origin, and the fact that your server now sees the CDN's IP unless you restore the real visitor IP from a header.
06Debugging the chain in practice
When something is wrong, test each link in order instead of guessing. Does the name resolve to the right IP? Can you open a TCP connection to port 443? Is the certificate valid for this hostname? What status code and headers come back? Is the server slow (high TTFB) or is the browser slow (long scripting or rendering in DevTools)? The browser's Network tab shows DNS, connect, TLS, waiting and download time for every file. The Performance tab and Lighthouse show parsing, layout and paint. On the server, access and error logs tell you whether the request even arrived.
dig +short example.com A # 1. DNS
nc -vz example.com 443 # 2. TCP port open?
openssl s_client -connect example.com:443 -servername example.com </dev/null | head -n 20 # 3. TLS
curl -sI https://example.com/ # 4. status + headers
sudo tail -f /var/log/nginx/access.log # 5. did it reach the server?
Use it when
- Diagnosing why a site is down, slow or showing a certificate error.
- Planning a new deployment: DNS, CDN, TLS and server choices all come from this chain.
- Explaining performance work (CDN, caching, image optimization) to non-technical people.
- Preparing for interviews: "what happens when you type a URL" is a classic question.
Skip it when
- You do not need to memorize every TCP flag to build a site; learn the depth you need when a problem appears.
- Do not optimize network round trips before fixing obvious server issues such as slow database queries.
Alternatives
- Native apps
Skip HTML rendering but still use DNS, TLS and HTTP to talk to APIs.
- WebSockets / SSE
Keep one connection open for real-time updates instead of request–response for every change.
- Static hosting on a CDN
Removes the application server from the path for pages that rarely change.
Best practices
- Serve everything over HTTPS with HTTP/2 or HTTP/3 enabled.
- Put a CDN in front of public sites and cache static assets with long, versioned lifetimes.
- Keep TTFB low: cache hot data, index database queries, keep servers close to users.
- Ship less JavaScript; defer non-critical scripts and avoid render-blocking resources.
- Compress text responses with Brotli or gzip and serve modern image formats (WebP, AVIF).
- Measure with real-user data (Core Web Vitals), not only with a fast laptop on office Wi-Fi.
Common mistakes
- Blaming "the server" without checking DNS, certificates or the browser first.
- Loading large blocking scripts in the head, delaying the first paint.
- Forgetting that a CDN or proxy hides the real visitor IP from logs and rate limits.
- Serving images at full camera resolution to mobile phones.
Deep dive
07Why the first 14 KB matter: TCP slow start
A new TCP or QUIC connection does not know how fast the path is, so it starts carefully. The sender may only have about ten packets in flight (the initial congestion window, roughly 14 KB) before it must wait for acknowledgements, then it doubles that amount each round trip while nothing is lost. So a 100 KB HTML document on a fresh connection needs several round trips, not one, even on a fast line. That is why inlining critical CSS and keeping the top of the HTML small helps the first paint, and why reused, already-warm connections feel so much faster. Packet loss makes the sender shrink its window again, which is why lossy mobile networks hurt more than raw bandwidth numbers suggest. Modern congestion control such as BBR reacts better to loss than older algorithms, but the physics of round trips stays.
- Small, server-rendered HTML with critical CSS gets painted sooner.
- Connection reuse (keep-alive, HTTP/2 multiplexing) skips slow start for later requests.
- Each extra origin means a new DNS lookup, handshake and cold window.
08How the browser decides what to fetch first
Browsers do not download resources in page order. While the main parser is blocked on a script, a preload scanner reads ahead in the raw HTML and starts fetching images, stylesheets and scripts it finds. Each request gets a priority: CSS and blocking scripts are high, images in the viewport are raised after layout, async scripts and below-the-fold images are low. You can steer this. rel=preload fetches something the scanner cannot see, such as a font referenced only inside CSS. fetchpriority=high marks the LCP image as important. 103 Early Hints lets the server or CDN send preload links before the HTML is ready, using server think-time. The trap is overuse: if everything is high priority, nothing is, and preloading unused files wastes bandwidth on the critical path.
<!-- In the <head>: help the browser find critical files early -->
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
<img src="/img/hero.avif" width="1200" height="630" fetchpriority="high" alt="Product hero">
<img src="/img/footer.webp" width="400" height="300" loading="lazy" alt="Team photo">
<script src="/js/app.3f9a1c.js" defer></script>
09The layers of cache between user and database
A request can be answered at many layers, and each one is cheaper than the next. In the browser: the back/forward cache keeps whole pages in memory for instant back navigation; the memory and HTTP disk caches hold files according to Cache-Control; a service worker can answer from its own cache, even offline. Then the CDN edge, sometimes with a regional tier in front of the origin. On the origin, a reverse proxy like nginx can cache whole responses (microcaching for a few seconds absorbs traffic spikes). Inside the app, Redis or memory caches hold computed data, and the database has its own buffer pool. The engineering question is always the same: where can this answer be safely reused, for whom, and for how long? Personalised data can only live in caches keyed to that user.
10Trust along the chain: what can be spoofed
Each step trusts something. Plain DNS answers can be forged on a hostile network, which is why DNSSEC exists and why encrypted DNS (DNS over HTTPS or TLS) hides lookups from the local network. The real protection, though, is TLS: even if DNS sends you to the wrong IP, the attacker cannot present a valid certificate for example.com, so the browser stops. HSTS removes the first insecure http:// request that an attacker could intercept. Inside the browser, the same-origin policy keeps one site from reading another site's data, cookies with SameSite limit cross-site requests, and Content-Security-Policy restricts which scripts may run. On the server side, anything in the request (headers, cookies, X-Forwarded-For) is user input until a trusted proxy vouches for it.
Real-world scenarios
Fast in the office, slow for users abroad
Problem
The site feels instant for the team near the data center, but users on another continent report three to four second loads. Server metrics look healthy.
How to solve it
Measure from where the users are: run curl timing from a remote VPS or a multi-region test and compare DNS, connect, TLS and TTFB. If connect and TLS each take around 150 ms, the problem is distance, not code. Put a CDN in front so handshakes end at a nearby edge, cache static assets with long versioned lifetimes and, if pages are public, cache HTML briefly at the edge. Enable HTTP/2 and HTTP/3, remove extra third-party origins, and cut redirect chains. Then check real-user Core Web Vitals by country to confirm the improvement.
Good TTFB, but LCP is over four seconds
Problem
The HTML arrives in 200 ms, yet the main image appears late on mobile. Lighthouse flags the LCP element as a large hero image.
How to solve it
The delay is in the browser, so look at the waterfall. Typical causes: the hero image is set as a CSS background or injected by JavaScript, so the preload scanner cannot find it; it is lazy-loaded by mistake; it is a 3 MB JPEG. Fix it by using a normal img tag with width and height, fetchpriority=high and no loading=lazy, serving AVIF or WebP at the right size with srcset, and preconnecting to the image CDN. Move render-blocking scripts to defer. Re-test on a throttled mobile profile and check field data after a few days.
Some users still see the old server after a migration
Problem
The A record was switched to a new server an hour ago. Most traffic moved, but a few customers still see the old site and its old data.
How to solve it
That is cached DNS, not a broken deploy. Check what TTL the old record had: resolvers may keep it until it expires, and some clients cache longer. Confirm the authoritative answer with dig against the nameserver, and compare with public resolvers. Keep the old server running, and either make it read-only with a banner or proxy its traffic to the new server so writes do not split across two databases. Next time, lower the TTL to 300 seconds a day ahead. Once old-server access logs go quiet, decommission it.
Cheat sheet
- Time each phase of a request
curl -o /dev/null -s -w "%{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}\n" https://example.com/- Resolve a name via a public resolver
dig +short example.com A @1.1.1.1- Check a TCP port is open
nc -vz example.com 443- See the certificate and TLS version
openssl s_client -connect example.com:443 -servername example.com -brief </dev/null- Headers only
curl -sI https://example.com/- Hit a specific server, bypassing DNS
curl -sI https://example.com/ --resolve example.com:443:203.0.113.10- Trace the network path and packet loss
mtr -rwc 50 example.com- Lab performance audit
npx lighthouse https://example.com --view- Make the LCP image a priority
<img src="/hero.avif" fetchpriority="high" width="1200" height="630" alt="">
In my real projects
- I run production Laravel and Next.js sites on Ubuntu servers with nginx in front, and walk this chain when diagnosing incidents.
- Cloudflare sits in front for DNS and basic DDoS protection on sites I manage, with HTTPS everywhere and auto-renewing certificates.
- I read server logs to trace production issues back to the exact request, such as a localization middleware bug and an image-to-WebP conversion bug.
Questions & answers
Q1What happens when you type a URL and press Enter?
The browser parses the URL and checks caches. If it has no IP, it resolves the name through a recursive resolver, which walks root, TLD and authoritative nameservers. It opens a TCP connection to port 443 and runs a TLS handshake, verifying the certificate. Then it sends an HTTP request with headers and cookies. The server, often nginx in front of an app, runs code, may query a database, and returns a status, headers and a body. The browser parses HTML into the DOM, CSS into the CSSOM, runs scripts, calculates layout, paints and composites. A CDN may answer from the edge without touching the origin at all.
Q2What is TTFB and how would you improve it?
Time to First Byte is the time from sending the request to receiving the first byte of the response. It includes DNS, connection and TLS setup, network latency and the server's processing time. To improve it I first check server time: slow queries, missing indexes, N+1 queries, no application cache. Then I look at distance: a CDN or edge cache brings content closer and reuses warm connections to the origin. HTTP/2 or HTTP/3 and keep-alive cut handshake costs. For pages that rarely change, caching full HTML at the edge can bring TTFB down from hundreds of milliseconds to a few dozen.
Q3What is the critical rendering path?
It is the sequence the browser must finish before it can paint: download and parse HTML into the DOM, download and parse CSS into the CSSOM, run blocking scripts, combine everything into a render tree, compute layout and paint. Anything that blocks it delays the first meaningful paint. CSS blocks rendering and classic scripts block parsing. To shorten it I inline or prioritize critical CSS, add defer to scripts, preload the hero image and main font, and avoid large client-side bundles. The aim is that the largest visible element appears quickly, which is what LCP measures.
Q4Why does a CDN make a site faster, and what are the risks?
Most delay on the web is round trips, not bandwidth. A CDN terminates TCP and TLS at an edge server close to the visitor, so handshakes take a few milliseconds instead of a long intercontinental trip. Cached assets are served from the edge, and misses travel to the origin over warm, reused connections. The risks are configuration: caching private or personalized pages by accident, wrong SSL mode between edge and origin, losing the real client IP in logs and rate limiting, and stale content after deploys. Clear cache rules, versioned asset filenames and a purge step in deployment handle most of them.
Q5What is the difference between TCP and UDP, and why does the web use both now?
TCP gives a reliable, ordered byte stream: it retransmits lost packets and delivers data in order, at the cost of a handshake and head-of-line blocking when a packet is lost. UDP just sends datagrams with no ordering or delivery guarantees, which is lighter. HTTP/1.1 and HTTP/2 run on TCP. HTTP/3 runs on QUIC, which is built on UDP but adds its own reliability, encryption and independent streams in user space. That lets one lost packet delay only its own stream, and it combines the transport and TLS handshakes, which helps a lot on mobile networks.
Senior-level questions
S1How would you design for a global audience with one origin server?
I would keep the single origin, which is simple to operate, and move as much as possible to the edge. Static assets get hashed names and year-long caching on a CDN. Public HTML is cached at the edge for seconds to minutes with stale-while-revalidate, and purged on publish. Personalised parts load from small API calls, or the page is split so the shell is cacheable. A tiered cache reduces origin hits further. Writes still travel to the origin, so I keep API responses small and make them idempotent for safe retries. The trade-off is cache invalidation complexity and eventual consistency for content. Multi-region origins only pay off when write latency or availability requirements justify the much harder data replication.
S2Where would you look first when p95 latency doubles but p50 stays the same?
A stable median with a worse tail usually means some requests hit a slow path, not that everything got slower. I split by dimension: route, region, device, cache status, and upstream. Common causes are cache misses after a deploy or purge, a specific query that lost its index, lock contention, garbage collection or a worker pool running out so requests queue, a slow third-party call without a timeout, or packet loss on one network. Server-side, I compare upstream response time with total request time in nginx logs to separate queueing from work. Tracing with request IDs shows where the extra time sits. The fix depends on the cause, but timeouts, pool sizing and caching the slow path are typical.
S3SSR, static generation or a client-rendered SPA: how do they change the chain?
Static generation produces HTML at build time, so the CDN can answer everything and TTFB is minimal; the cost is rebuilds or revalidation when content changes. Server-side rendering builds HTML per request, giving fresh, personalised content and good LCP, but TTFB depends on server and data speed, so caching and streaming matter. A client-rendered SPA sends a small HTML shell and a large JavaScript bundle; the first paint of real content waits for download, parse, execution and API calls, which hurts LCP and SEO on slow devices, but later navigation is fast. Modern frameworks mix them per route: static for marketing pages, SSR or streaming for dynamic pages, and client components only where interactivity is needed.
Glossary
- RTT
- Round-trip time: how long a packet takes to reach the server and come back. Most web delay is counted in RTTs.
- TTFB
- Time to First Byte: from sending a request until the first byte of the response arrives.
- DOM
- Document Object Model: the tree of elements the browser builds from HTML, which JavaScript can read and change.
- CSSOM
- The browser's parsed model of all CSS rules, combined with the DOM to decide how things look.
- LCP
- Largest Contentful Paint: when the biggest visible element, often a hero image or heading, finishes rendering. Good is under 2.5 s.
- INP
- Interaction to Next Paint: how quickly the page visually responds to clicks, taps and key presses. Good is under 200 ms.
- CLS
- Cumulative Layout Shift: how much visible content jumps unexpectedly while loading. Good is under 0.1.
- Origin
- Your own server behind a CDN; also, in browser security, the scheme + host + port of a URL.
- Edge
- A CDN server close to the visitor that terminates connections and serves cached content.
- Preload scanner
- A secondary browser parser that reads ahead in HTML to start downloading resources early.
Keep learning
Have a product in mind?Let's build it.
Tell me about your idea, your product or your team. I usually reply within one working day.