Network waterfalls are the single most honest view of how your CDN actually performs. Not synthetic scores, not averaged RUM metrics, but the sequential, color-coded reality of DNS, TCP, TLS, TTFB, and content download for every resource on the page. If you can read a waterfall fluently, you can distinguish an edge cache hit from a shield miss, a slow origin from a congested PoP, and a client-side bottleneck from a true network delay.
This guide shows you how to analyze CDN waterfalls like an infrastructure engineer: what each timing phase means, which patterns signal misconfiguration, and how to turn a waterfall into an actionable optimization plan.
1. Anatomy of a Network Waterfall
Every bar in Chrome DevTools, WebPageTest, or SpeedCurve represents one resource. The bar is segmented by phase. Understanding those segments is prerequisite to any CDN performance debugging workflow.
In DevTools, the colors map directly to the Resource Timing API:
- Queueing / Stalled (white/gray): Browser waiting due to connection limits, priority, or disk cache. Not a CDN issue, but it delays everything.
- DNS Lookup: Resolving the CDN hostname. Should be near-zero after the first request if DNS TTL and pre-resolve are correct.
- Initial Connection / TCP: SYN/SYN-ACK handshake to the edge PoP. High values indicate PoP distance or packet loss.
- SSL / TLS: Handshake negotiation. Expect 1-RTT with TLS 1.3, 2-RTT with TLS 1.2. Reused connections (HTTP/2 or HTTP/3) eliminate this.
- TTFB / Waiting: Time from request sent to first byte received. This is where CDN cache status lives. A HIT is 20-80ms; a MISS adds origin latency + shield hop.
- Content Download: Transfer time. Correlates with asset size, compression, and HTTP/2/3 multiplexing efficiency.
Pro tip: Enable the Server-Timing and X-Cache response headers in your waterfall tool to overlay cache status directly on the bar. Without it, you are guessing.
2. How to Read a CDN Waterfall Correctly
Start at the top, not the bottom. The document request (HTML) dictates everything downstream.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
Step 1: Validate the HTML delivery
If / or /index.html has a TTFB of 400ms+ and shows x-cache: MISS, your origin is on the critical path for every page load. No amount of image optimization will fix that. Check whether HTML should be cached at the edge with short-TTL caching strategies or served stale-while-revalidate. For dynamic HTML, consider tiered caching and Argo-style smart routing.
Step 2: Check connection reuse
All static assets should reuse the same TCP/TLS connection to the CDN hostname. If you see repeated DNS + TLS bars for every asset, you have a connection coalescing failure: multiple hostnames without SAN coverage, HTTP/1.1 without keep-alive, or a sharded domain that predates HTTP/2. Consolidate to one CDN hostname and enable HTTP/2 or HTTP/3.
Step 3: Separate TTFB from Download
A long blue Download bar means large payload or slow throughput. A long green TTFB bar means server-side wait. Engineers often misdiagnose a 600ms TTFB on a 12KB JSON file as a bandwidth problem. It is not. It is a cache miss, origin query, or edge compute delay. Filter by TTFB in WebPageTest to isolate it.
Step 4: Read priority and sequencing
Modern browsers prioritize resources. Your waterfall should show CSS and fonts early, images later, and low-priority scripts deferred. If a 1.2MB hero image blocks CSS, you have a priority inversion — often caused by early preloads or render-blocking scripts injected via tag managers. Use fetchpriority="high" only for the LCP image.
3. CDN-Specific Signals Hidden in the Waterfall
A generic waterfall tells you when. CDN headers tell you why.
| Signal | Where to Find It | Healthy Value | What It Means |
|---|---|---|---|
| Cache Status | X-Cache, CF-Cache-Status, Age |
HIT Age > 0 | Served from edge RAM. TTFB should be <100ms globally. |
| Shield / Tiered Cache | X-Cache: MISS, HIT (two-tier) |
Edge MISS, Shield HIT | Edge fetched from shield, not origin. TTFB 80-180ms. |
| Origin Latency | Server-Timing: origin;dur=... |
<150ms | Time origin took to generate response. High = DB/query issue. |
| TLS Version | Server-Timing or DevTools Security panel |
TLS 1.3, 0-RTT or 1-RTT | TLS 1.2 adds ~60ms. Enable TLS 1.3 at edge. |
| HTTP Version | Protocol column (h2, h3) | h2 or h3 | h1.1 prevents multiplexing; causes connection queueing. |
| Revalidation | 304 Not Modified + REVALIDATED |
Small 304, ~30ms | Conditional request. Use stale-while-revalidate to hide it. |
To expose these, configure your CDN to emit Server-Timing. Example for Cloudflare Workers or Fastly VCL:
add_header Server-Timing "cdn-cache;desc=HIT, edge;dur=12, origin;dur=0" always;
# For MISS: origin;dur=214, shield;dur=42
Also verify Cache-Control and CDN-Cache-Control are distinct. A common mistake is sending Cache-Control: private, no-store for authenticated HTML, which also prevents edge caching unless you override with CDN-Cache-Control: max-age=60, stale-while-revalidate=600. See our guide on cache invalidation for safe patterns.
4. Common Waterfall Anti-Patterns and Fixes
Pattern 1: The Origin Staircase
Every static asset shows a 300-700ms TTFB with MISS, each stair-stepped because the browser hits the 6-connection limit. Root cause is usually a cache key that includes a cookie, query string, or Vary: * header. Fix: normalize cache keys, strip unnecessary cookies at the edge, and set Vary: Accept-Encoding only. One bad Vary can drop hit ratio from 96% to 40%.
Pattern 2: TLS Handshake Storm
You see purple TLS bars on 15+ resources. This happens with domain sharding (img1.cdn.com, img2.cdn.com) or when using multiple CDN hostnames without a wildcard cert. With HTTP/2 and HTTP/3, sharding hurts. Consolidate assets to a single hostname and enable 0-RTT where safe. For third parties, use preconnect, not dns-prefetch alone.
<link rel="preconnect" href="https://cdn.flyfishnwa.com" crossorigin>
<link rel="preload" as="image" href="/hero-1200.webp" fetchpriority="high" imagesrcset="/hero-600.webp 600w, /hero-1200.webp 1200w">
Pattern 3: The Long Green Bar on Images
A 900ms TTFB on a 200KB WebP that should be cached. Check Age and Cache-Control. If Age: 0 and HIT, the object was just inserted — maybe a recent purge. If MISS repeatedly, your image optimizer is generating unique URLs per request or signing URLs with short expiry. Stabilize URLs and cache transformed images at the edge with CDN image optimization settings.
Pattern 4: Blocking Third Parties
A single analytics or A/B script with 800ms TTFB blocks rendering because it is loaded synchronously in the head. The waterfall shows a gap — no other resources start until it completes. Move it to async or defer, or load via edge worker and serve from your CDN hostname to benefit from connection reuse.
Pattern 5: HTML Slow, Assets Fast
HTML TTFB is 650ms (MISS), but all subsequent assets are HIT and fast. This is an origin or shield latency problem, not an edge problem. Enable stale-while-revalidate and stale-if-error for HTML, or use an edge cache lock (request coalescing) to prevent thundering herd on popular pages.
5. Optimization Playbook: From Waterfall to Fix
Use this sequence after capturing a waterfall in WebPageTest (3 runs, cable profile, with Preserve User Data off):
- Measure hit ratio: Export HAR, count HIT vs MISS. Aim for >92% for static, >75% for HTML with tiered cache. Low ratio = fix cache keys first.
- Collapse connection overhead: Ensure h2/h3, TLS 1.3, single hostname, and preconnect. Each eliminated handshake saves 60-120ms on 4G.
- Reduce TTFB variance: If MISS TTFB is >300ms, add shield PoP closer to origin, enable origin keep-alive, and tune origin concurrency. A 20ms shield RTT beats a 90ms cross-country origin fetch.
- Compress and prioritize: Verify Brotli (level 5-6) for text, AVIF/WebP for images, and correct priorities. A 40% smaller download bar often matters more than 20ms TTFB.
- Defer non-critical: Anything not needed for LCP should not compete for bandwidth in the first 2 seconds. Defer, lazy-load, or edge-inject.
Validate with code-level timing:
curl -w "dns:%{time_namelookup} tcp:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n" \
-H "Pragma: no-cache" -s -o /dev/null -D - https://cdn.flyfishnwa.com/app.9a2c.css | grep -i "x-cache\|age\|server-timing"
// In browser console — Resource Timing for LCP candidate
performance.getEntriesByType('resource').filter(r=>r.name.includes('hero')).map(r=>({
name: r.name.split('/').pop(),
ttfb: (r.responseStart - r.requestStart).toFixed(1),
download: (r.responseEnd - r.responseStart).toFixed(1),
proto: r.nextHopProtocol
}))
Pair waterfall analysis with broader security and routing checks. A misconfigured WAF rule can add 150ms of edge compute before cache lookup, visible as inflated TTFB even on HITs — review your CDN security guide to ensure bot checks run after cache, not before.
6. Building a Repeatable Debugging Workflow
Waterfalls are snapshots. For reliability, automate:
- Synthetic waterfalls: Schedule WebPageTest or Catchpoint tests from 3+ regions, alert if median HIT TTFB >120ms or hit ratio <90%.
- RUM correlation: Tag RUM beacons with
cacheStatusfromServer-Timingto correlate real-user LCP with HIT/MISS in your analytics. - HAR diffing: On deploy, diff waterfalls before/after. A new
Set-Cookieon static assets will instantly show as new MISS bars.
When you file a ticket with your CDN provider, include the HAR, the CF-Ray or X-Served-By PoP ID, and the specific resource waterfall. “Site is slow” is unactionable; “DFW PoP, MISS TTFB 680ms on /api/menu.json, origin dur 540ms” gets fixed in hours.
Mastering waterfall analysis turns the CDN from a black box into a transparent pipeline. Start with cache status, then connections, then priorities — in that order — and most performance issues resolve to a handful of header or key misconfigurations rather than infrastructure limits.