Network Tab & Waterfall Analysis
Learn how to read the Network tab waterfall, diagnose slow requests, understand caching headers, and optimize resource loading. The practical debugging skill every frontend engineer needs.
Table of Contents
Overview
The Network tab in Chrome DevTools shows every HTTP request the browser makes — HTML documents, stylesheets, scripts, images, API calls, fonts, and more. It's your window into what's loading, when, and how fast.
The waterfall chart visualizes these requests on a timeline, showing exactly when each resource starts loading, how long each phase takes (DNS, connection, TTFB, download), and which requests block others.
Together, they let you answer the most important performance question: why is this page slow? Whether it's a slow API, a massive image, a render-blocking stylesheet, or too many requests — the Network tab tells you exactly where the time goes.
The debugging mindset
When a page is slow, open the Network tab first. Sort by time, look at the waterfall, and find the longest bar. That's your bottleneck. Fix that one thing and re-test.
Introduction to Network Tab
The Network tab captures all network activity from the moment you open it. Every resource the page requests appears as a row with details about size, timing, status, and type.
How to Open It
macOS: Cmd + Option + I → Network tab Windows: F12 or Ctrl + Shift + I → Network tab Pro tip: Check "Disable cache" to test without browser cache Pro tip: Reload the page with the tab open to capture everything
Types of Resources
Documents
HTML pages — the initial document and any iframes. This is the first request and everything else depends on it.
Stylesheets & Scripts
CSS files (render-blocking) and JS bundles (parser-blocking). These directly impact how fast the page renders.
XHR / Fetch
API calls made by JavaScript. These fetch data for dynamic content — user info, product lists, dashboard data.
Images & Media
JPG, PNG, WebP, SVG, video files. Often the largest resources on a page by total bytes.
Fonts
WOFF2, WOFF font files. Can cause invisible text (FOIT) if not loaded with font-display: swap.
Other
WebSocket connections, preflight CORS requests, service worker fetches, manifest files.
Quick overview stats
The bottom bar of the Network tab shows total requests, total transfer size, total resources size (uncompressed), DOMContentLoaded time, and Load time. These give you an instant health check of the page.
Understanding a Network Request
Click any request in the Network tab to see its full details. Every request has several tabs of information. Here's what each one tells you.
| Tab | What It Shows | Why It Matters |
|---|---|---|
| Headers | Request URL, method, status code, request/response headers | Debug CORS issues, check cache headers, verify API endpoints |
| Preview | Formatted response body (JSON, HTML, images) | Quick check if the API returned expected data |
| Response | Raw response body text | See exact payload, debug malformed responses |
| Timing | Detailed timing breakdown (DNS, TTFB, download) | Identify which phase of the request is slow |
| Initiator | What triggered this request (script, parser, redirect) | Trace back to the code that made the request |
Key Request Properties
Request URL: https://api.example.com/v1/products?page=1 Method: GET Status Code: 200 OK (or 304 Not Modified if cached) Remote Address: 104.26.10.78:443 ── Request Headers ────────────────────────────── Accept: application/json Authorization: Bearer eyJhbGci... Cache-Control: no-cache ── Response Headers ───────────────────────────── Content-Type: application/json; charset=utf-8 Content-Length: 4,832 Cache-Control: public, max-age=3600 ETag: "abc123" Content-Encoding: br (Brotli compressed) ── Timing ─────────────────────────────────────── Queued: 2ms DNS Lookup: 15ms Initial Connection: 45ms (TCP + TLS) Request Sent: 0.5ms Waiting (TTFB): 120ms ← server processing time Content Download: 8ms Total: 190.5ms
HTTP Status Codes to Know
| Code | Meaning | What to Check |
|---|---|---|
| 200 | OK — request succeeded | Normal. Check response body for expected data. |
| 301/302 | Redirect — resource moved | Adds a round-trip. Check if redirect is necessary. |
| 304 | Not Modified — use cached version | Good! Means caching is working. Very fast response. |
| 404 | Not Found — resource doesn't exist | Wasted request. Remove the reference or fix the URL. |
| 500 | Server Error — backend crashed | Check server logs. May cause high TTFB before failing. |
Size column: two numbers
The Network tab shows two sizes: transferred (compressed, over the wire) and resource (uncompressed, in memory). If transferred is much smaller, compression is working. If they're the same, compression is missing — enable Brotli/Gzip on your server.
Waterfall Chart
The waterfall chart is the most important visualization in the Network tab. Each request is a horizontal bar on a shared timeline. The position shows when it started, the length shows how long it took, and the color segments show where time was spent.
Time (ms) 0 100 200 300 400 500 600 700 │ │ │ │ │ │ │ │ index.html ████░░░░░░░░░░░│ │ │ │ │ │ DNS TTFB DL │ │ │ │ │ │ │ │ │ │ │ │ styles.css ───────────────██████░░░░░░░ │ │ │ │ (waits for HTML) TTFB DL │ │ │ │ │ │ │ │ app.js ───────────────██████████░░░░░░░░░░ │ │ │ (waits for HTML) TTFB Download │ │ │ │ │ │ hero.jpg ──────────────────────────────────████████░░░░░░░ │ (waits for CSS/JS to finish) TTFB Download │ │ api/data ──────────────────────────────────────████░░░░░░░ │ (waits for JS to execute) TTFB DL │ Legend: ██ = Active (DNS/Connect/TTFB) ░░ = Download ── = Waiting
Timing Breakdown (Hover Over Any Bar)
Hover over any waterfall bar to see the detailed timing breakdown. Each phase tells you something specific about where time is being spent.
| Phase | What Happens | Slow? Check This |
|---|---|---|
| Queueing | Request waits in browser queue (max 6 connections per origin) | Too many requests to same origin. Use CDN or HTTP/2. |
| DNS Lookup | Resolving domain name to IP address | New domain? Add dns-prefetch. Usually 0ms for repeat visits. |
| Initial Connection | TCP handshake + TLS negotiation | New origin? Add preconnect. HTTP/2 reuses connections. |
| SSL | TLS certificate exchange and encryption setup | Part of initial connection. Unavoidable for HTTPS. |
| Request Sent | Browser sends the HTTP request bytes | Almost always <1ms. Not a bottleneck. |
| Waiting (TTFB) | Time to First Byte — server processing time | Slow API? Backend issue. Optimize server, add caching. |
| Content Download | Receiving the response bytes | Large file? Compress, resize images, code-split JS. |
┌──────────────────────────────────────────────────────────┐ │ Total: 340ms │ │ │ │ ┌─────┐┌────┐┌──────────┐┌─┐┌──────────────┐┌────────┐ │ │ │Queue││DNS ││Connection││S││ TTFB (180ms)││Download│ │ │ │ 5ms ││15ms││ 40ms ││S││ ← Server ││ 95ms │ │ │ │ ││ ││ TCP+TLS ││L││ processing ││ │ │ │ └─────┘└────┘└──────────┘└─┘└──────────────┘└────────┘ │ │ │ │ ⚠ TTFB is 53% of total time — optimize the backend │ └──────────────────────────────────────────────────────────┘
The two things to check first
TTFB (green bar) — if it's long, the server is slow. Optimize the backend, add server-side caching, or use a CDN. Content Download (blue bar) — if it's long, the file is too big. Compress it, resize images, or code-split JavaScript.
Identifying Bottlenecks
The waterfall tells a story about your page load. Here are the patterns that indicate performance problems.
Pattern 1: High TTFB (Slow Server)
api/products ──────────████████████████████████░░░ │← 800ms TTFB →│ DL ⚠ The green "Waiting" segment is huge. Server took 800ms to start responding. Fix: Optimize database queries, add server caching, use a CDN for static content, add Redis for API responses.
Pattern 2: Large Downloads
bundle.js ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ TTFB │←──── 2MB download over 3G ────────→│ ⚠ The blue "Content Download" segment is huge. File is too large for the connection speed. Fix: Code-split, tree-shake, enable Brotli compression, lazy-load non-critical modules.
Pattern 3: Request Waterfall (Sequential Loading)
index.html ████░░░ styles.css ────────████░░░ @import ────────────────████░░░ ← discovered late! font.woff2 ────────────────────────████░░░ ← even later! ⚠ Each resource waits for the previous one. CSS @import creates a chain. Font discovered only after CSS. Fix: Replace @import with <link> tags (parallel). Preload fonts: <link rel="preload" href="font.woff2" as="font">
Pattern 4: Too Many Requests (Connection Saturation)
Request 1 ████░░░░ Request 2 ████░░░░ Request 3 ████░░░░ Request 4 ████░░░░ Request 5 ████░░░░ Request 6 ████░░░░ Request 7 ──────────────████░░░░ ← queued! waiting for slot Request 8 ──────────────████░░░░ ← queued! Request 9 ──────────────────────████░░░░ ← queued even longer ⚠ HTTP/1.1 allows max 6 connections per origin. Requests 7+ are queued until a slot opens. Fix: Use HTTP/2 (multiplexing), bundle files, use a CDN (different origin = separate connection pool).
Sort by time to find the worst offender
Click the "Time" column header in the Network tab to sort requests by total duration. The slowest request floats to the top — that's your primary optimization target.
Request Prioritization & Loading
The browser doesn't load all resources equally. It assigns a priority to each request based on resource type, position in the document, and attributes. Understanding this helps you control what loads first.
| Resource | Default Priority | Why |
|---|---|---|
| HTML document | Highest | Everything depends on it. Must load first. |
<link rel="stylesheet"> in head | Highest | Render-blocking. Browser can't paint without it. |
<script> in head (no defer/async) | High | Parser-blocking. Stops DOM construction. |
<link rel="preload"> | High | Developer explicitly marked as important. |
<script defer> | Low | Downloads in parallel, executes after DOM. |
<img> above the fold | Medium | Visible content, but not render-blocking. |
<img loading="lazy"> | Low | Below the fold. Deferred until near viewport. |
<link rel="prefetch"> | Lowest | For future navigations. Fetched when idle. |
<!-- ✅ Boost priority of hero image (LCP element) --> <img src="hero.webp" fetchpriority="high" alt="Hero" /> <!-- ✅ Lower priority of below-fold image --> <img src="footer-bg.webp" fetchpriority="low" loading="lazy" alt="" /> <!-- ✅ Preload critical font (discovered late by default) --> <link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin /> <!-- ✅ Preconnect to API origin (saves DNS + TCP + TLS) --> <link rel="preconnect" href="https://api.example.com" />
Check priority in DevTools
Right-click the column headers in the Network tab and enable the "Priority" column. This shows the actual priority the browser assigned to each request. If your hero image is "Low" priority, add fetchpriority="high".
Filtering & Debugging
The Network tab can show hundreds of requests. Filtering helps you focus on what matters.
Filter by Resource Type
The filter bar at the top has buttons for each resource type. Click one to show only that type.
| Filter | Shows | Use When |
|---|---|---|
| All | Every request | Overview of full page load |
| Fetch/XHR | API calls only | Debugging API responses, slow endpoints |
| JS | JavaScript files | Finding large bundles, checking code-splitting |
| CSS | Stylesheets | Checking render-blocking CSS, unused styles |
| Img | Images | Finding unoptimized images, missing lazy-load |
| Font | Web fonts | Checking font loading, preload effectiveness |
| Doc | HTML documents | Checking redirects, initial document timing |
Useful Debugging Techniques
── Search ────────────────────────────────────────── Cmd + F in Network tab → search by URL, header, or response body Example: search "products" to find all product API calls ── Block Requests ────────────────────────────────── Right-click a request → "Block request URL" Test what happens if a resource fails to load ── Replay Request ────────────────────────────────── Right-click a XHR/Fetch request → "Replay XHR" Re-send the exact same request without reloading the page ── Copy as cURL ──────────────────────────────────── Right-click → "Copy as cURL" Paste into terminal to reproduce the request outside the browser ── Preserve Log ──────────────────────────────────── Check "Preserve log" to keep requests across page navigations Essential for debugging redirects and multi-page flows ── Override Headers ──────────────────────────────── Right-click → "Override headers" Test different cache headers or auth tokens without code changes
The filter search box
The text filter supports special syntax: status-code:404 finds failed requests, larger-than:100k finds large files, domain:api.example.com filters by origin, -domain:cdn.example.com excludes an origin.
Real Example Walkthrough
Let's walk through a real slow page load and diagnose it using the Network tab — the kind of analysis you'd do at work or in an interview.
Scenario: E-commerce Homepage Takes 5s to Load
Time (ms) 0 500 1000 1500 2000 2500 3000 3500 4000 4500 5000 │ │ │ │ │ │ │ │ │ │ index.html ██░░ 80ms (OK) styles.css ────██████████░░░░░░░░░░░ ⚠ 350KB uncompressed! 900ms total theme.css ────────────────────────██████░░░░ ⚠ @import inside styles.css — sequential! 400ms bundle.js ────██████████████████████████████░░░░░░░░░░░░░░░░░░░░ ⚠ 1.2MB bundle! 2.1s total. Parser-blocking. analytics ────████░░░ Blocking script in <head>. 200ms wasted. hero.jpg ──────────────────────────────────────────────████████████░░░░░░░░░░░░░░ ⚠ 4MB unoptimized JPG. Starts late (blocked by JS). 1.8s download. api/products ──────────────────────────────────────────████████████████░░░ ⚠ TTFB: 800ms (slow backend). Starts after JS executes. DOMContentLoaded: 2.8s Load: 5.1s Requests: 47 Transferred: 6.2MB
Diagnosis: 5 Problems Found
- ⚠styles.css is 350KB uncompressed — no Brotli/Gzip compression enabled
- ⚠theme.css loaded via @import — creates a sequential chain instead of parallel
- ⚠bundle.js is 1.2MB — no code-splitting, no tree-shaking
- ⚠analytics.js is a blocking script in <head> — delays everything
- ⚠hero.jpg is 4MB — unoptimized, no WebP, no responsive sizes
The Fix
| Problem | Before | After | Savings |
|---|---|---|---|
| CSS compression | 350KB (no compression) | 45KB (Brotli) | ~87% smaller |
| CSS @import chain | Sequential (900ms + 400ms) | Two parallel <link> tags | ~400ms saved |
| JS bundle | 1.2MB single bundle | Route-based code-splitting | Initial: ~200KB |
| Analytics script | Blocking <script> | Added async | Unblocks parsing |
| Hero image | 4MB JPG | 120KB WebP + srcset + preload | ~97% smaller |
After fixes: DOMContentLoaded ~800ms, Load ~1.5s, Transferred ~400KB. FCP improved from 2.8s to ~600ms.
The debugging process
(1) Sort by Size to find the biggest files. (2) Sort by Time to find the slowest requests. (3) Look at the waterfall for sequential chains. (4) Check the bottom bar for total requests and transfer size. Fix the biggest wins first.
Performance Optimization Techniques
Every optimization maps to something you can verify in the Network tab. Here are the techniques organized by strategy.
A. Reduce Number of Requests
Bundle Files
Combine multiple JS/CSS files into fewer bundles. Modern bundlers (Vite, webpack) do this automatically. Fewer requests = less connection overhead.
Remove Unused Assets
Use the Coverage tab to find unused CSS/JS. Remove dead code, unused libraries, and unnecessary third-party scripts. Every request costs time.
Inline Small Resources
CSS under 14KB can be inlined in the HTML to eliminate a round-trip. Small SVG icons can be inlined instead of loaded as separate files.
B. Optimize File Size
Enable Brotli/Gzip Compression
Server-side compression reduces text files (HTML, CSS, JS, JSON) by 60-80%. Brotli is ~15-20% better than Gzip. Check the Content-Encoding response header.
Minify CSS & JS
Remove whitespace, comments, and shorten variable names. Reduces file size by 20-40%. Build tools handle this in production mode.
Optimize Images
Use WebP/AVIF (30-50% smaller than JPG). Serve responsive sizes with srcset. Compress aggressively. Images are typically 50%+ of page weight.
C. Improve Loading Strategy
Code-Split JavaScript
Use dynamic import() to split bundles by route. Only load the JS needed for the current page. Verify in Network tab: initial bundle should be <200KB.
Lazy Load Below-Fold Images
Add loading='lazy' to images below the viewport. The browser won't fetch them until they're near the viewport. Verify: they shouldn't appear in initial waterfall.
Preload Critical Resources
Use <link rel='preload'> for fonts, hero images, and critical CSS. Moves them earlier in the waterfall. Verify: they should appear near the top.
D. API Optimization
Reduce API Payload Size
Return only the fields the client needs (GraphQL or sparse fieldsets). A 500KB JSON response that could be 50KB is wasting bandwidth and parse time.
Add HTTP Caching
Set Cache-Control headers on API responses. Cached responses show as '(disk cache)' or '(memory cache)' in the Network tab — 0ms TTFB.
Optimize Backend Response Time
High TTFB means the server is slow. Add database indexes, use Redis caching, optimize queries. Target: TTFB under 200ms for API calls.
Caching Insights
Caching is the single most effective performance optimization. A cached response loads in 0ms with 0 bytes transferred. The Network tab shows you exactly what's cached and what isn't.
Cache Headers
| Header | Example | What It Does |
|---|---|---|
| Cache-Control | max-age=31536000 | Cache for 1 year. Browser won't re-request until expired. |
| Cache-Control | no-cache | Always revalidate with server (still caches, but checks ETag). |
| Cache-Control | no-store | Never cache. Every request goes to the server. Use for sensitive data. |
| ETag | "abc123" | Content fingerprint. Browser sends If-None-Match to check if changed. |
| Last-Modified | Wed, 15 Jan 2025 | Timestamp. Browser sends If-Modified-Since to check freshness. |
Memory Cache vs Disk Cache
| Cache Type | In Network Tab | Speed | When Used |
|---|---|---|---|
| Memory cache | (memory cache) | ~0ms | Resources from current session. Cleared on tab close. |
| Disk cache | (disk cache) | ~1-5ms | Persisted to disk. Survives tab close and browser restart. |
| 304 Not Modified | 304 | ~50-100ms | Server confirmed cache is still valid. Only headers transferred. |
| No cache | 200 (full download) | 100ms+ | Full response downloaded. No caching benefit. |
── Static assets (JS, CSS, images with hash in filename) ── Cache-Control: public, max-age=31536000, immutable → Cache forever. Filename hash changes on content change. → Example: app.a1b2c3.js, styles.x7y8z9.css ── HTML documents ───────────────────────────────────────── Cache-Control: no-cache → Always revalidate. Ensures users get latest version. → Server returns 304 if unchanged (fast). ── API responses ────────────────────────────────────────── Cache-Control: public, max-age=60, stale-while-revalidate=300 → Cache for 60s. Serve stale for 5min while revalidating. → Good for data that changes but isn't real-time. ── Sensitive data (user profile, auth) ──────────────────── Cache-Control: private, no-store → Never cache. Always fetch fresh from server.
How to check in DevTools
Look at the "Size" column. If it says "(memory cache)" or "(disk cache)", the resource was served from cache — 0 bytes transferred. If it shows a byte count, it was downloaded from the server. Check the response headers for Cache-Control to understand why.
Advanced Insights
These advanced features help you simulate real-world conditions and get deeper insights from the Network tab.
Network Throttling
Simulate Slow 3G (400Kbps), Fast 3G (1.5Mbps), or custom speeds. Reveals how your site performs on real mobile connections. Essential for testing.
Disable Cache
Check 'Disable cache' to force all requests to go to the server. Essential for testing first-visit performance. Only active while DevTools is open.
Preserve Log
Keep network requests across page navigations and redirects. Essential for debugging login flows, OAuth redirects, and multi-page sequences.
Block Requests
Right-click → Block request URL/domain. Test what happens when a CDN is down, a third-party script fails, or an API is unreachable.
HAR File Export
Right-click in the Network tab → "Save all as HAR with content" to export the full network trace. Share it with teammates, attach to bug reports, or analyze in tools like WebPageTest. HAR files capture every request with full timing, headers, and response bodies.
Testing like real users
Enable "Slow 3G" throttling + "Disable cache" to simulate a first-time visitor on a mobile connection. This is the worst-case scenario your users experience. If it's fast here, it's fast everywhere.
Common Mistakes
These mistakes lead to slow pages and missed optimization opportunities.
Ignoring the waterfall shape
Looking only at individual request times without seeing the overall pattern. A waterfall that's tall and narrow (sequential) is much worse than one that's short and wide (parallel).
✅Look at the waterfall shape first. Parallel is good, sequential chains are bad. Fix chains with preload, parallel <link> tags, and HTTP/2.
Too many API calls on page load
Making 10+ API calls on initial load, each waiting for the previous one. Common in SPAs that fetch user data, then permissions, then content, then preferences — all sequentially.
✅Combine related API calls into a single endpoint. Use GraphQL or BFF (Backend for Frontend) pattern. Parallelize independent requests with Promise.all().
Unoptimized images
Serving 4MB hero images, using PNG for photos, not providing responsive sizes. Images are often 50-80% of total page weight.
✅Use WebP/AVIF, compress aggressively, serve responsive sizes with srcset, lazy-load below-fold images. Target: hero image under 200KB.
Not using caching
Every request goes to the server because Cache-Control headers are missing or set to no-store. Repeat visitors download everything again.
✅Set max-age=31536000 for hashed static assets. Use no-cache (not no-store) for HTML. Add ETag for API responses.
Render-blocking resources in <head>
Multiple large CSS files and synchronous scripts in <head> that block rendering. The browser can't paint until all of them download and process.
✅Inline critical CSS, defer JS, load non-critical CSS async. Use the Coverage tab to find unused CSS/JS.
CSS @import chains
Using @import inside CSS files creates sequential download chains. The browser discovers each file only after downloading the previous one.
✅Replace @import with <link> tags in HTML. They download in parallel. Or bundle CSS at build time.
Interview Questions
Network and loading performance questions test your practical debugging skills. Interviewers want to hear a systematic approach with specific tools and metrics.
Q:How do you debug a slow network request?
A: Open the Network tab, find the slow request, and click it to see the Timing breakdown. Check TTFB — if it's high, the server is slow (optimize backend, add caching). Check Content Download — if it's high, the file is too large (compress, resize, code-split). Check Queueing — if it's high, too many requests are competing for connections (use HTTP/2, reduce requests).
Q:What is waterfall analysis and why is it important?
A: Waterfall analysis is reading the Network tab's timeline visualization where each request is a horizontal bar showing when it started and how long each phase took. It reveals sequential chains (resources waiting for others), connection saturation (too many requests), and the critical path (which resources block rendering). It's the primary tool for diagnosing page load performance.
Q:What is TTFB and how do you improve it?
A: TTFB (Time to First Byte) is the time between sending a request and receiving the first byte of the response. It measures server processing time. Improve it by: optimizing database queries, adding server-side caching (Redis), using a CDN for static content, enabling HTTP/2 server push, and reducing server-side computation. Target: under 200ms for API calls, under 100ms for static assets.
Q:How does the browser prioritize resource loading?
A: The browser assigns priority based on resource type and position. Highest: HTML document, CSS in <head>. High: synchronous scripts, preloaded resources. Medium: above-fold images. Low: deferred scripts, async scripts. Lowest: lazy images, prefetch. You can influence priority with fetchpriority='high'/'low', preload, defer, async, and loading='lazy'.
Q:What is the difference between preload, prefetch, and preconnect?
A: preload fetches a resource with high priority for the current page (fonts, hero images). prefetch fetches a resource at low priority for future navigations (next page's JS). preconnect establishes a connection (DNS + TCP + TLS) to a third-party origin early, saving 100-300ms when the actual request happens. Use preload for critical current-page resources, preconnect for third-party APIs/CDNs.
Q:How do you optimize page load using Network tab insights?
A: (1) Sort by Size — find and optimize the largest files (compress, code-split, resize images). (2) Sort by Time — find the slowest requests (optimize TTFB, reduce payload). (3) Read the waterfall — eliminate sequential chains (replace @import with <link>, preload fonts). (4) Check caching — ensure static assets have long max-age. (5) Check the bottom bar — reduce total requests and transfer size.
Q:Explain Cache-Control headers and their impact on performance.
A: Cache-Control tells the browser how to cache a response. max-age=N caches for N seconds without revalidation. no-cache always revalidates with the server (but still caches — returns 304 if unchanged). no-store never caches. immutable means the content will never change (used with hashed filenames). public allows CDN caching, private restricts to the user's browser. Proper caching can reduce repeat-visit load time by 80%+.
Q:What causes HTTP/1.1 connection saturation and how do you fix it?
A: HTTP/1.1 allows max 6 concurrent connections per origin. If a page makes 20+ requests to the same origin, requests 7+ are queued. Fix: upgrade to HTTP/2 (multiplexes unlimited requests over one connection), use a CDN (different origin = separate pool), bundle files to reduce request count, or domain-shard (spread across subdomains — last resort).
Practice Section
Apply your Network tab knowledge to these real-world scenarios.
Slow Page Load Debugging
A page takes 6 seconds to load. The Network tab shows 85 requests, 8MB transferred, and the waterfall is very tall with many sequential chains. How do you approach this?
Answer: Step 1: Sort by Size — find the biggest files. Likely unoptimized images (compress to WebP, add lazy loading) and a large JS bundle (code-split by route). Step 2: Sort by Time — find the slowest requests. Check TTFB for slow APIs. Step 3: Look at the waterfall for sequential chains — replace CSS @import with parallel <link> tags, preload fonts. Step 4: Check caching — add Cache-Control headers to static assets. Step 5: Reduce request count — bundle small files, inline critical CSS. Target: under 30 requests, under 1MB transferred.
Finding the Slow API
A dashboard page loads quickly but the data section takes 3 seconds to appear. The Network tab shows 4 XHR requests. How do you find which API is slow?
Answer: Filter by 'Fetch/XHR' to isolate API calls. Sort by Time to find the slowest one. Click it and check the Timing tab: if TTFB is high (e.g., 2.5s), the backend is slow — optimize the query, add caching, or paginate the response. If Content Download is high, the payload is too large — return only needed fields, paginate, or compress. Also check if the 4 requests are sequential (each waiting for the previous) — if so, parallelize with Promise.all().
CSS Blocking Rendering
Users see a white screen for 2 seconds before content appears. The Network tab shows a 400KB CSS file loading from a third-party CDN. Why is this happening and how do you fix it?
Answer: CSS is render-blocking — the browser won't paint until the CSSOM is complete. A 400KB CSS file from a third-party CDN adds DNS lookup + connection + TTFB + download time before any rendering. Fix: (1) Add <link rel='preconnect'> for the CDN origin to save connection time. (2) Inline critical above-the-fold CSS in a <style> tag. (3) Load the full CSS asynchronously with rel='preload' + onload swap. (4) Use the Coverage tab to find unused CSS rules — likely 60-80% is unused on this page.
Cheat Sheet (Quick Revision)
One-screen reference for Network tab debugging.
Quick Revision Cheat Sheet
First step: Open Network tab, disable cache, reload page. Look at waterfall shape.
TTFB: Time to First Byte. Server processing time. High = slow backend. Target: <200ms.
Content Download: Time to download response body. High = file too large. Compress or split.
Waterfall shape: Parallel (wide) = good. Sequential (tall) = bad chains. Fix with preload, <link>.
Sort by Size: Find largest files. Compress images (WebP), code-split JS, enable Brotli.
Sort by Time: Find slowest requests. Check TTFB vs download. Fix the biggest bottleneck.
Filter: Fetch/XHR: Isolate API calls. Find slow endpoints. Check payload size.
Cache-Control: max-age=31536000 for hashed assets. no-cache for HTML. no-store for sensitive data.
(memory cache): Served from RAM. 0ms. Current session only.
(disk cache): Served from disk. ~1-5ms. Persists across sessions.
304 Not Modified: Server confirmed cache is valid. Only headers transferred. Fast.
HTTP/2: Multiplexes requests over one connection. No 6-connection limit. Use it.
preload: Fetch critical resource early (fonts, hero image). High priority.
preconnect: Establish connection to third-party origin early. Saves 100-300ms.
Coverage tab: Shows unused CSS/JS per file. Red = unused. Remove or lazy-load.
Throttling: Test with Slow 3G + Disable cache = worst-case first visit.