Network cabinets and cabling

Page Load Anatomy: Building a Dissectible Model of the Network

Most of a page load happens before a single byte of HTML arrives, and almost nobody can say how much. Page Load Anatomy is a dissectible model of that gap: pull out a layer — DNS, TCP, TLS, HTTP, the render path — see it working on its own, then change one thing and watch what moves downstream.

A simulator, not an animation

There is no shortage of pretty “how the internet works” diagrams. They animate a packet flying across a wire and teach nothing actionable, because the numbers are decorative.

This is a deterministic model built on real protocol arithmetic, with tests asserting the model matches the specs. When it says a cold HTTP/1.1 connection over TLS 1.2 spends seven round trips before the first byte of HTML, that comes from counting actual flights: four for a cold DNS walk from root to TLD to authoritative, one for the TCP handshake, two for the TLS 1.2 handshake.

Switch to HTTP/3 with 0-RTT resumption and a warm DNS cache and the same page spends zero. On a 100ms link that is 380ms of pure setup you either pay or you do not — and no amount of shrinking your JavaScript touches it.

Things the model makes obvious

Each of these is an assertion in the test suite, not a claim in a README.

  • The first 14.6KB is special. TCP’s initial congestion window is ten segments at a 1460-byte MSS. Anything inside it arrives in one round trip; one byte over costs a second.
  • A CDN beats halving your HTML. Cutting a document from 12KB to 6KB changes nothing when both fit the first window. Shortening every round trip changes everything.
  • Bandwidth barely matters for small pages. Dropping from 1000Mbps to 5Mbps on an 8KB page costs under 20ms. Tripling the round-trip time more than doubles the load.
  • HTTP/1.1 queues. Thirteen assets across six connections stack up. The same page over HTTP/2 does not queue at all.
  • HTTP/3 saves exactly one round trip over HTTP/2, because QUIC folds the transport and crypto handshakes together.

The two rows worth staring at are bandwidth and latency next to each other. Most engineers optimize the one that barely moves.

Predict and observe

The model predicts. The browser reports. Both matter, and they are different halves.

It turns out the browser already dissects every request for you — PerformanceResourceTiming exposes DNS, connect, TLS, request, response and download timings for everything a page loads. Almost nobody reads it. The observer turns those entries into the same span shape the simulator produces, so a measured request and a predicted one can be drawn by the same code and compared directly.

That also surfaces something naive implementations get wrong. A cross-origin response without a Timing-Allow-Origin header has every phase timing zeroed by the browser. Drawing those as zero-length bars tells the viewer the request was instant, which is the exact opposite of what a withheld timing means. Those entries are flagged as opaque, and no phase spans are fabricated for them.

One instrument, many specimens

The panel ships as a custom element rather than a framework component, so it drops into Next.js, Astro, Vite, or a plain script tag unchanged, with Shadow DOM keeping the host page’s CSS out. The standalone build is 6.6KB, 3KB gzipped, and registers itself on load.

Its first home is the Rental Property Analyzer, where it does something better than measure performance: it proves a privacy claim. That app says your data never leaves the device, and the panel shows you the empty request log that makes the claim checkable.

The AI part comes later, on purpose

An LLM request is the strangest thing on the wire right now — time-to-first-token instead of TTFB, a response that streams for eight seconds, a request payload that grows every turn because the whole conversation is resent.

None of that is legible without a baseline. Push it through a black box and you learn nothing. Push it through a bench where you already know what a normal request costs and the differences are obvious. That is the only reason the pipe came first.