Web performance, explained

Make the web faster.

Understand what the browser is actually doing.

Interactive experiments, visualisations and practical techniques for building faster websites. Lighthouse tells you that something is wrong. This site teaches you why.

Explore the experiments Optimise a page

HTTP/1.1 · 6 connections · illustrative
  • Queued
  • DNS
  • TCP
  • TLS
  • TTFB
  • Download

12 experiments · 4 tracks

Change a variable. Watch the browser respond.

Network

How bytes get to the browser, and how to need fewer of them.

  1. 01

    The Request Queue

    Why isn’t loading 30 images just 30 requests?

    Connection limits, DNS, TCP, TLS and what HTTP/2 and HTTP/3 change. The “six at once” rule, taken apart.

    Level
    Intermediate
    Impact
    Time
    8 min
  2. 06

    HTTP Caching

    Why does a repeat visit sometimes still wait on the network?

    Cache-Control, validation, 304s, immutable files and CDNs, plus what compression does and doesn’t change.

    Level
    Intermediate
    Impact
    Time
    10 min
  3. 07

    Service Workers

    What happens when you put a programmable proxy between the page and the network?

    Install, activate and update; cache-first, network-first and stale-while-revalidate; offline, and the stale-cache trap.

    Level
    Advanced
    Impact
    Time
    12 min
  4. 08

    Resource Hints

    Preload, prefetch, preconnect: which one, and when?

    The hints and priorities compared, including fetchpriority and Early Hints. When each helps and when it competes.

    Level
    Advanced
    Impact
    Time
    9 min
  5. 11

    Instant Navigation

    How can the next page load before you click?

    Back/forward cache, prefetch and prerender with Speculation Rules, and what can go wrong.

    Level
    Advanced
    Impact
    Time
    8 min

Assets

What you send: images, fonts, JavaScript and everyone else’s scripts.

  1. 02

    Images

    What does the browser do with a 2.4 MB hero?

    Formats, srcset, lazy loading, priority and sprite sheets, including when a sprite sheet is the wrong call.

    Level
    Beginner
    Impact
    Time
    12 min
  2. 04

    Fonts

    Why does your page feel broken for half a second?

    FOIT, FOUT, font-display, preload, subsetting and variable fonts, compared side by side.

    Level
    Intermediate
    Impact
    Time
    8 min
  3. 03

    JavaScript

    Why is a kilobyte of script dearer than a kilobyte of image?

    Download, parse, compile, execute. Watch long tasks block the main thread and swallow a tap.

    Level
    Intermediate
    Impact
    Time
    10 min
  4. 09

    Third-Party Scripts

    Who else is using your main thread?

    Add analytics, ads and chat widgets one at a time and watch blocking time, layout shift and bytes grow.

    Level
    Intermediate
    Impact
    Time
    9 min

Rendering

What the browser does with it once it has arrived.

  1. 05

    Critical Rendering Path

    Why can’t the browser just show the page?

    HTML to DOM, CSS to CSSOM, render tree, layout, paint, composite. Add a blocking resource and watch it stall.

    Level
    Advanced
    Impact
    Time
    14 min
  2. 10

    CSS

    Why can 200 KB of CSS cost more than 200 KB of images?

    Selector matching, style recalculation, content-visibility and containment.

    Level
    Advanced
    Impact
    Time
    10 min

Measuring

Knowing whether any of it worked.

  1. 12

    Lab vs Field

    Why does my 95 score not match what users feel?

    A distribution of real visits, percentiles, Core Web Vitals thresholds, and how a single lab run misleads.

    Level
    Intermediate
    Impact
    Time
    8 min

Training mode

Optimise this page.

A deliberately bad page starts at 24. Fix the hero image, lazy-load what’s below the fold, sort out fonts and cut the JavaScript, and see exactly which change moved the score.

Start the challenge

24 90 BEFOREAFTER

Common misconceptions

Don’t memorise rules. Understand the system.

Not universally true

“Browsers only load six resources at once.”

Six connections per origin is an HTTP/1.1-era habit. HTTP/2 and HTTP/3 multiplex many requests over one connection, and the real limits depend on protocol, origin, connection reuse and priorities.

Outdated

“More requests are always bad.”

On HTTP/2 and HTTP/3 a request is far cheaper than it was, and a cached request is free. Many small, separately cacheable files can beat one bundle that changes on every release.

It moves one request, and crowds the rest

“Preload makes everything faster.”

Preload starts a request sooner and ranks it higher. Everything else now has more to compete with for the same bandwidth. It helps where discovery is late, and overused it delays the resources that matter most.

Not for what’s on screen

“Lazy loading everything is better.”

Lazy loading saves bytes by waiting, and waiting is the wrong thing for the hero. Above-the-fold images should load as early as possible.

Usually, not always

“A smaller file is always faster.”

A more aggressive format can cost more to decode. A smaller file discovered late, or behind a queue, still arrives late. Bytes are one of several costs.

One simulated visit was fast

“A high Lighthouse score means my website is fast.”

A lab run is one visitor on a fixed profile. Real visits differ, and what happens after load shapes the experience. Lab scores, field data and perceived responsiveness can all disagree.

All 32 misconceptions →

How this site is built

The site is its own case study.

  • Static HTML. This page ships no JavaScript at all. An experiment loads only its own widget, when it scrolls into view.
  • Two self-hosted variable fonts, one preloaded, each with a size-adjusted local fallback so the swap does not shift the layout.
  • Every request goes to this origin. No third-party scripts, no analytics, no cookies.
  • Honours prefers-reduced-motion and fits a 320px screen without sideways scrolling.