The second visit
Reload the page you just loaded and it appears almost instantly. That is not one optimisation doing its job. It is four, each removing a different part of the cost, and they have nothing to do with each other.
Four savings, four mechanisms
| Stage | What is reused | Where it is remembered |
|---|---|---|
| DNS | The address for the name | The resolver, for the record TTL |
| TCP | The open connection itself | The browser, while it stays open |
| TLS | A session ticket | The client, until it expires |
| HTTP | The response body | The cache, per RFC 9111 |
Notice how differently they fail. A DNS entry expires on a timer nobody consults; a connection is closed by whichever side loses patience first; a TLS ticket is a bearer credential with a lifetime; and an HTTP response can be stale and still useful, which is a state the other three have no equivalent of.
Fresh, stale, and the four assets that were never asked for
Four of the page's assets produced no network activity at all. Their cached copies were still fresh — the time since they were stored is less than the lifetime the server gave them — so the browser used them without asking anyone.
That is the strongest form of caching, and it is qualitatively different from the 304: a fresh hit is not a faster request, it is no request. It also explains why cache lifetimes are a design decision rather than a performance knob. A long lifetime means you cannot change the file; the usual answer is to change its name instead, and put a hash in it.
Key takeaways
- “Cached” is four unrelated mechanisms — a DNS entry, an open connection, a TLS ticket, and an HTTP response — each saving a different stage.
- A fresh cache hit is not a faster request; it is no request, and no server is involved at all.
- A 304 is a real round trip that saves only the body. That is still usually a very good trade.
- Staleness is an HTTP idea. The other three mechanisms have no equivalent of “out of date but still useful”.
- A long cache lifetime is unrecallable, which is why immutable assets get content-hashed URLs and the HTML that points at them does not.