Skip to main content

🚦 Network Analysis and Performance

Every click on the web triggers a conversation between a browser and a server. This lesson teaches you to eavesdrop on that conversation in the Network panel, read the timing of every request, and turn what you see into concrete speed wins that users actually feel.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Trace the request–response lifecycle from DNS lookup through content download
  • Read HTTP methods, status codes, and headers and know what each one is telling you
  • Interpret a waterfall chart and pinpoint where time is being lost
  • Measure and reason about the three Core Web Vitals β€” LCP, INP, and CLS
  • Apply the highest-impact optimizations: caching, modern image formats, deferral, and resource hints

Estimated Time: 35–45 minutes  β€’  Difficulty: Beginner–Intermediate

Hands-on: Profile a real page under a throttled connection and write a prioritized optimization plan.

In This Lesson

Why Network Performance Matters

Think of network performance as the highway system for your web application. A beautiful app that arrives slowly feels broken β€” users bounce, conversions drop, and search rankings slip. The good news is that most slowness is visible and measurable the moment you open your browser's developer tools.

Performance work is a loop, not a one-time chore: you measure what's happening, diagnose the biggest offender, apply a fix, then measure again to confirm the win. Everything in this lesson feeds that loop.

πŸ“– A guiding number

Studies from Google and Amazon repeatedly find that every extra second of load time measurably increases bounce rate. You don't need to memorize the exact figures β€” just internalize that speed is a feature, and it's one you can engineer deliberately.

The Request–Response Lifecycle

Before you can analyze network traffic, you need a mental model of how a browser and a server talk. When you type an address and press Enter, a predictable sequence of steps unfolds.

sequenceDiagram participant B as Browser participant D as DNS participant S as Server B->>D: Resolve example.com? D-->>B: 93.184.216.34 B->>S: Open TCP + TLS connection B->>S: GET / HTTP/2 S-->>B: 200 OK (HTML) B->>S: GET /style.css S-->>B: 200 OK (CSS) B->>S: GET /app.js S-->>B: 200 OK (JS) B->>S: GET /hero.avif S-->>B: 200 OK (image)

Broken into steps, every interaction follows this pattern:

  1. DNS resolution β€” the domain name is translated into an IP address (cached after the first lookup).
  2. Connection setup β€” a TCP connection is opened, plus a TLS handshake for HTTPS.
  3. Request sent β€” the browser transmits an HTTP request with a method, headers, and possibly a body.
  4. Server processing β€” the server does its work (queries a database, renders a template) and builds a response.
  5. Response received β€” the server streams the response back; the browser parses, renders, and requests any further resources it discovers.
🍽️ A useful analogy: Loading a page is like ordering a multi-course meal. Your first request is the menu (the HTML). Once you read it, you place follow-up orders for each dish (CSS, JS, images). A complex page, like a complex meal, needs many trips to the kitchen β€” and the slowest dish sets the pace of the whole dinner.

HTTP: Methods, Status Codes & Headers

HTTP (HyperText Transfer Protocol) is the language every web request speaks. Three parts of it show up constantly in the Network panel: the method, the status code, and the headers.

HTTP methods

MethodPurposeTypical use
GETRetrieve a resourcePage loads, reading API data, images
POSTCreate / submit dataForm submissions, creating records
PUTReplace a resourceFull updates to an existing record
PATCHPartially updateChanging one field on a record
DELETERemove a resourceDeleting a record
HEADHeaders only, no bodyChecking if a resource changed
OPTIONSAsk what's allowedCORS preflight checks

A social app maps neatly onto these: GET the feed, POST a new post, PATCH an edit, DELETE a post β€” each method signals a different intent to the server.

Status codes

The first digit of a status code tells you the category at a glance:

  • 2xx β€” Success: 200 OK, 201 Created, 204 No Content
  • 3xx β€” Redirection: 301 Moved Permanently, 302 Found, 304 Not Modified (a cache win β€” the browser reused what it had)
  • 4xx β€” Client error: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests
  • 5xx β€” Server error: 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout

⚠️ Field story: chasing a 504

During a high-traffic sale, a team saw a cluster of 504 errors on their payment endpoint. Filtering the Network panel to just those requests revealed the payment gateway was timing out under peak load. The fix wasn't in the frontend at all β€” it was adding retry logic and a request queue on the server. The Network panel simply pointed the flashlight at the right place.

Headers worth knowing

Request headersResponse headers
Accept β€” types the client can handleContent-Type β€” the media type returned
Authorization β€” credentials / tokensCache-Control β€” how long to cache
Content-Type β€” type of the request bodyETag β€” version fingerprint for validation
Cookie β€” stored cookiesSet-Cookie β€” cookies to store

A team once cut load time roughly 30% purely by tuning Cache-Control and ETag so browsers reused files instead of re-downloading them. Headers are where much of your caching strategy lives.

Reading the Network Panel

Open DevTools (F12 or Ctrl+Shift+I), click Network, and reload the page. You'll see every request in a table, with a summary of totals along the bottom.

Filtering to find the signal

  • Type filters: the buttons for Fetch/XHR, JS, CSS, Img, Font, Doc narrow the list instantly.
  • Property filters: type queries like status-code:404 or method:POST.
  • Negation: prefix with a minus sign, e.g. -status-code:200 to see everything that didn't succeed.
  • Combine with spaces (logical AND): method:POST larger-than:10k finds large POST requests.

To isolate flaky API calls, a filter like status-code:500 method:POST can surface a pattern in seconds that would take ages to spot by eye.

The waterfall chart

Click any request and open its Timing tab, or read the waterfall column directly. Each bar breaks a request into phases:

A network waterfall chart Six resources loading over time, each split into queuing, DNS, connection, TLS, waiting for the first byte, and content download phases. 0 ms 300 ms 600 ms 900 ms index.html style.css app.js hero.avif font.woff2 api/data connect waiting (TTFB) download
Figure 1 β€” A waterfall chart. A long amber bar (waiting/TTFB) points to slow server work; a long green bar (download) points to a large or uncompressed file.

Key phases to read:

  • Queuing / Stalled: the request is waiting its turn (browser connection limits, prioritization).
  • DNS + Connect + TLS: one-time setup cost per origin.
  • Waiting (TTFB): Time To First Byte β€” how long the server took to start responding.
  • Content Download: how long the bytes took to arrive β€” driven by file size and compression.

A long TTFB says "look at the server or your CDN." A long download bar says "this file is too big β€” compress it, resize it, or split it." One team traced a slow product page to a fat TTFB, added a Redis cache in front of their database, and cut API response times dramatically.

πŸ’‘ Watch the Protocol column

Enable the Protocol column (right-click the headers). h2 means HTTP/2 and h3 means HTTP/3 β€” both multiplex many requests over one connection, so the old trick of "spread files across domains" is unnecessary and often counterproductive on modern servers.

Core Web Vitals

Old metrics like "page load time" measure when the browser technically finished, not when the page felt ready. Google's Core Web Vitals fix that by measuring the user's actual experience across three axes: loading, interactivity, and visual stability.

graph TD A[Core Web Vitals] --> B[LCP β€” Loading] A --> C[INP β€” Interactivity] A --> D[CLS β€” Visual Stability] B --> B1[Good: ≤ 2.5 s] C --> C1[Good: ≤ 200 ms] D --> D1[Good: ≤ 0.1]

Largest Contentful Paint (LCP)

LCP marks when the largest element in the viewport β€” usually a hero image or big headline β€” becomes visible. Good target: ≀ 2.5 s. Common fixes are compressing and preloading the hero image and removing render-blocking resources ahead of it.

Interaction to Next Paint (INP)

INP replaced First Input Delay as a Core Web Vital in March 2024. Where FID only measured the delay of the first interaction, INP looks at the responsiveness of interactions throughout the page's life, reporting the worst typical case. Good target: ≀ 200 ms. Poor INP usually traces to long JavaScript tasks blocking the main thread β€” break them up, defer non-critical scripts, and move heavy work to a Web Worker.

Cumulative Layout Shift (CLS)

CLS quantifies unexpected movement β€” the maddening jump when an image or ad loads late and shoves the button you were about to tap. Good target: ≀ 0.1. The cure is reserving space up front: set width/height (or aspect-ratio) on media, and pre-allocate space for anything injected later. One store cut CLS from 0.42 to 0.08 just by adding image dimensions, and mis-clicks on "Add to Cart" fell sharply.

βœ… How to measure them

  • Lighthouse (DevTools β†’ Lighthouse) β€” lab audit with actionable suggestions.
  • Performance panel β€” live Web Vitals overlay while you interact.
  • PageSpeed Insights β€” combines lab data with real-user field data.
  • web-vitals JS library β€” collect real-user metrics in production.

High-Impact Optimizations

Once you can measure, these are the moves that consistently deliver the biggest wins per hour of effort.

1. Serve images in modern formats and the right size

Images are usually the heaviest thing on a page. Prefer AVIF or WebP over JPEG/PNG, serve responsive sizes, and lazy-load anything below the fold:

<img
  src="hero-800.avif"
  srcset="hero-400.avif 400w, hero-800.avif 800w, hero-1600.avif 1600w"
  sizes="(max-width: 600px) 100vw, 50vw"
  width="1600" height="900"
  alt="Product on a wooden table">

<!-- Below the fold: let the browser defer the download -->
<img src="review.avif" loading="lazy" width="600" height="400" alt="Customer review">

Note the explicit width and height β€” they double as your CLS insurance.

2. Cache aggressively with the right headers

Static, fingerprinted assets can be cached essentially forever; HTML should revalidate. Set this on the server:

# Fingerprinted assets that never change (app.9f2a1c.js)
Cache-Control: public, max-age=31536000, immutable

# HTML that may change β€” always revalidate
Cache-Control: no-cache

Pair long cache lifetimes with cache busting: a build tool renames app.js to app.9f2a1c.js whenever its contents change, so returning visitors reuse everything except what actually updated.

3. Stop render-blocking resources

A <script> in the <head> without defer blocks parsing. Inline the tiny bit of CSS needed for the first screen, and defer the rest:

<script src="critical.js" defer></script>   <!-- runs after HTML parses, in order -->
<script src="analytics.js" async></script>  <!-- runs whenever it arrives -->

Use defer for app code that depends on the DOM, and async for independent third-party scripts like analytics.

4. Tame third-party scripts

Widgets, chat bubbles, and ad tags are often the single worst offenders because they run on someone else's server. Audit them in the Network panel, load them async, self-host where licensing allows, and lazy-load on interaction. One marketing team removed 2.3 s of load time by replacing heavy social widgets with lightweight buttons that only pulled the real script when clicked.

⚠️ Do & Don't

Do measure before and after every change so you can prove the win.

Do fix the biggest bar in the waterfall first, not the easiest.

Don't preload everything β€” it dilutes priority and can slow the resources that truly matter.

Don't optimize on your fast office Wi-Fi only; throttle to "Slow 4G" to feel what real users feel.

Resource Hints & Preloading

Resource hints let you tell the browser about work it will need soon, so it can start early. Use them surgically.

HintWhat it doesBest for
dns-prefetchResolves a domain earlyThird-party domains used later
preconnectDNS + TCP + TLS earlyAn origin you'll hit very soon
preloadHigh-priority fetch for this pageLate-discovered critical fonts, hero image
prefetchLow-priority fetch for a future pageThe likely next navigation
<!-- Warm up a connection to your API or CDN -->
<link rel="preconnect" href="https://cdn.example.com" crossorigin>

<!-- Preload a critical font to avoid invisible text -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>

<!-- Preload the LCP hero image -->
<link rel="preload" href="/hero-800.avif" as="image">

<!-- Prefetch the page the user will probably visit next -->
<link rel="prefetch" href="/product-details.html">

πŸ’‘ The golden rule of hints

Add hints one at a time and re-measure. A hint that helps one page can hurt another by stealing bandwidth from something more important. If you can't measure a benefit, remove it.

Hands-on Exercise & Quiz

πŸ‹οΈ Profile & plan: a sluggish product page

Objective: Practice the full measure β†’ diagnose β†’ plan loop on a real page.

Instructions:

  1. Open any content-heavy page you use (a shop, a news site) and open DevTools β†’ Network.
  2. In the throttling dropdown, choose Slow 4G, tick Disable cache, and reload.
  3. Record four numbers from the summary bar: requests, transferred size, finish time, and DOMContentLoaded.
  4. Sort by Size and list the five largest resources. Then sort by the waterfall and note the request with the longest TTFB.
  5. Run a Lighthouse report and write down LCP, INP (or TBT as its lab proxy), and CLS.
  6. Write a 5-item optimization plan, ordered by expected impact. For each, name the metric it should improve.
πŸ’‘ Hint

The biggest bar in the waterfall is almost always where to start. If it's a green download bar, the file is too big (compress/resize). If it's an amber waiting bar, the server or an API is slow (cache/optimize the backend). Images and third-party scripts are the usual top offenders.

βœ… Example plan
  1. Convert the 1.8 MB hero JPEG to AVIF and preload it β†’ improves LCP.
  2. Add loading="lazy" + explicit dimensions to 20 below-fold thumbnails β†’ improves CLS and total transfer.
  3. Defer the 300 KB analytics bundle with async β†’ improves INP.
  4. Add Cache-Control: immutable to fingerprinted JS/CSS β†’ speeds up repeat visits.
  5. Cache the slow /api/products response (long TTFB) behind a CDN or Redis β†’ improves LCP and TTFB.

🎯 Quick Quiz

Question 1: In a waterfall chart, a request has a very long amber "Waiting (TTFB)" bar but a short download bar. What is the most likely cause?

Question 2: Which Core Web Vital replaced First Input Delay (FID) in 2024, and what does it measure?

Question 3: You add width and height attributes to every image on a page. Which metric are you most directly improving?

Summary

πŸŽ‰ Key Takeaways

  • Every page load is a request–response lifecycle: DNS β†’ connect β†’ request β†’ server work β†’ response.
  • Read HTTP by its method, status code, and headers; the first status digit tells you the category.
  • The waterfall localizes slowness: long TTFB = server; long download = big file.
  • Optimize for the user with Core Web Vitals β€” LCP, INP, CLS (INP replaced FID in 2024).
  • The biggest wins: modern images, smart caching, deferred scripts, tamed third parties, and surgical resource hints β€” always measured before and after.

πŸ“š Further Reading

πŸš€ What's Next?

Now that you can spot where a page is slow or broken over the network, the next lesson β€” Debugging in the Browser β€” teaches you to find why your JavaScript misbehaves, using breakpoints, the console, and a systematic debugging process.

πŸŽ‰ Great work!

You can now open any page, read its network story, and turn it into a plan. That's a skill professional teams rely on every single day.