FrontendLesson 4 of 410 min

Why pages feel slow

Four different kinds of slow, and how to tell which one you have before you optimise the wrong thing.

"Slow" is four different problems wearing the same coat. Optimising the wrong one is the single most common waste of effort in web development, and it is very easy to do when an AI hands you a plausible-looking fix.

The four slows
  1. Slow to start
    Distance and handshakes. Fix by moving closer or caching.
  2. Slow to arrive
    Too many bytes. Fix by sending less.
  3. Slow to think
    The server is doing expensive work, usually a database query. Fix upstream.
  4. Slow to draw
    The browser is running too much JavaScript. Fix by doing less on the client.

These have different symptoms. Slow to start affects the first request only. Slow to arrive gets worse on mobile networks. Slow to think shows up as a long pause before anything appears, and gets dramatically worse under load. Slow to draw makes the page appear but freeze when you interact with it.

The tool for telling these apart already lives in your browser. Open developer tools, go to the network panel, reload. Every request is a bar on a timeline. A long bar that is mostly waiting is a thinking problem. A long bar that is mostly downloading is a size problem. A short set of bars followed by a frozen page is a drawing problem.

Is it slow for everyone, or slow for me?

Your machine is fast, your connection is fast, and your database has twelve rows in it. Almost every performance surprise in production is a gap between those three things and reality.

One practical habit: before you accept any performance fix, write down which of the four slows you believe you have and what evidence you have for it. If you cannot fill that in, you are guessing, and a confident suggestion from a coding assistant is not evidence.

What to remember

  • There are four unrelated kinds of slow and they need opposite fixes.
  • The network panel tells you which one you have in about thirty seconds.
  • Database slowness scales with data volume, so it hides during development.

Terms in this lesson

Field notes

Loaded from a deliberately slow source. The lesson above was already readable while this was still travelling. That is streaming, and it is the same trick a chat interface uses.

The bug was three caches deep

A team spent two days on a "deploy that did not work". The deploy was fine. A CDN rule was caching the HTML document itself for an hour, so every visitor kept getting the previous build. The fix was one header; finding it needed knowing the copies existed.

Reported by a solo founder, 2024

Nobody had opened the empty state

A product launched with a dashboard that looked superb with demo data and completely blank on day one. Every new signup saw an empty white rectangle and assumed the app was broken. Signup-to-activation doubled after a two-hour fix.

Common enough to be a cliché

resolved in 900ms · region iad1

Hide field notes toggles a search param the loader reads. With it off, the slow promise is never created, so nothing streams.