Twelve Seconds for a Dashboard
A dashboard page is measured on a 4G profile: 150 ms round-trip time, 8 Mbps downlink, no packet loss. The page issues 120 requests to a single origin: 1 HTML, 3 CSS, 5 JS, 96 small PNG icons and 15 JSON XHRs. The origin sits behind a proxy that strips the Connection header, so every request opens a new TCP connection and performs a full TLS 1.2 handshake. Server processing averages 40 ms per request and the server handles 8 requests concurrently. The browser opens at most 6 connections per origin. Modelled as 20 sequential waves of 6 requests, each request costs 1 RTT for TCP, 2 RTT for TLS 1.2, 1 RTT for the request/response, plus 40 ms of server time; a throttled replay reproduces 12.6 s. The target is 2.5 s. The proposal on the table is to buy a server with twice the CPU.
1. Reproduce the 12.6 s arithmetic and rank the contributors by share of the total.
Read the worked answer
Per-request cost on a fresh connection: 1 RTT (TCP) + 2 RTT (TLS 1.2) + 1 RTT (HTTP) + 40 ms server = 4 x 150 + 40 = 640 ms.
Waves: 120 requests at 6 connections per origin = 20 waves. 20 x 640 ms = 12,800 ms, which matches the 12.6 s replay within measurement noise (the browser overlaps some requests, so the observed figure is slightly lower than the model).
Share of the per-request budget:
- Handshake: 3 RTT = 450 ms, about 70% of the 640 ms.
- Data transfer and server time: 1 RTT + 40 ms = 190 ms, about 30%.
So 20 x 450 = 9,000 ms of the 12,800 ms - roughly 70% of the whole page load - is spent setting up connections that carry a 4 KB icon. The server work is 20 waves x 40 ms = 800 ms, about 6% of the total, because server time is overlapped 6 ways.
Evaluate the proposal against those numbers: doubling CPU halves per-request server time to 20 ms, so a wave costs 600 + 20 = 620 ms and the page takes 12.4 s. That is a 3% improvement for a hardware purchase. The proposal targets the 6% line item and leaves the 70% line item untouched.
2. Which single change gives the biggest win, what is the resulting estimate, and how does HTTP/2 change the picture?
Read the worked answer
The biggest win is eliminating per-request connection setup - fix the proxy so it stops stripping Connection, or terminate TLS at a layer that preserves keep-alive.
Keep-alive restored, same 6 connections:
- One handshake per connection: 6 x 450 ms happens once and overlaps, effectively about 450 ms of setup.
- Each request then costs 1 RTT + 40 ms = 190 ms. 20 waves x 190 ms = 3,800 ms.
- Total about 4.25 s - a 3x improvement from a configuration fix, and far past what the CPU upgrade achieves.
HTTP/2 over a single connection:
- One connection setup: 450 ms with TLS 1.2, or 150 ms with TLS 1.3 (one RTT).
- 120 streams multiplexed on one connection; the server handles 8 concurrently, so ceil(120/8) = 15 batches x 40 ms = 600 ms of server time.
- Payload: roughly 400-500 KB of icons and assets at 8 Mbps (about 1 MB/s) is roughly 0.5 s of transfer, plus one RTT for the last bytes.
- Total in the region of 1.5-1.7 s, inside the 2.5 s target.
Two cautions to state. First, HTTP/2 multiplexing removes application-level head-of-line blocking but not TCP-level blocking: a single lost packet stalls all streams, so on a lossy mobile profile the win shrinks and connection count should not be reduced blindly. Second, HTTP/2 makes domain sharding and image spriting counterproductive - splitting assets across hostnames multiplies the connection setup that HTTP/2 exists to amortise, and spriting 96 icons into one image destroys per-icon caching.
3. The team also proposes inlining all 96 icons as base64 in the HTML and enabling preconnect hints. Assess both, and say how you would verify the page meets 2.5 s.
Read the worked answer
Base64 inlining: it removes 96 requests, which in the current model cuts the page from 20 waves to 4 (24 requests) and would look like a huge win. But it is the wrong fix for three reasons. Encoding inflates bytes by about 33% and bypasses compression, so the HTML grows by roughly 130 KB - still cheap on 8 Mbps, but it is now a render-blocking download that must complete before first paint. The 96 icons can no longer be cached independently, so every dashboard change re-downloads all of them. And it hides the root cause: after the keep-alive fix those 96 requests cost 96 x 190 ms spread over 6 connections, about 3 s of the total - helpful to reduce, but not the dominant term. A single SVG sprite or an icon font gets most of the request reduction without the caching penalty.
Preconnect hints: useless here for the main origin, because the page's own origin is connected to anyway and the hint competes for the 6-connection budget. They help only for genuinely separate origins (CDN, API host), and HTTP/2 makes cross-origin splitting largely undesirable.
Verification plan:
- Synthetic: re-run the throttled 4G replay and compare waterfall total, time to first byte, first contentful paint and largest contentful paint before and after each change, one change at a time.
- Real user monitoring: p50/p75/p95 of the same metrics on the 4G profile, segmented by region, since RTT varies far more than server time and the whole argument rests on RTT.
- Confirm the fix at the wire level: check that responses carry Connection: keep-alive and that a single TCP connection handles multiple requests (browser devtools connection ID, or a capture), because a misconfigured proxy can silently re-disable it.
- Regression guard: an alert on requests-per-connection and on TLS handshakes per page load, so the setting cannot silently drift back.