# Performance

> Measure the Core Web Vitals, fix the largest offenders, and use the service worker to make launch feel instant.

import { Steps } from '@astrojs/starlight/components';

**Outcome:** a PWA that meets the Core Web Vitals thresholds and *feels* instant —
fast to launch, responsive to input, visually stable. Performance work is a loop:
measure, fix the biggest offender, measure again. Don't optimise by guesswork.

The metrics, thresholds, and what each one captures are described in the
[Core Web Vitals reference](/reference/performance/core-web-vitals/); this guide is the
procedure for moving them.

## The metrics you're moving

| Metric | What it measures | Good |
|---|---|---|
| LCP | Loading — largest element painted | ≤ 2.5s |
| INP | Responsiveness — input to next paint | ≤ 200ms |
| CLS | Visual stability — unexpected layout shift | ≤ 0.1 |

## Steps

<Steps>

1. **Measure first, on real conditions.** Run Lighthouse and capture field data
   (Web Vitals) on a mid-tier device and throttled network. Optimising before
   measuring wastes effort on the wrong thing. Definitions are in the
   [Core Web Vitals reference](/reference/performance/core-web-vitals/).

2. **Fix LCP — the largest paint.** Preload the hero image/font, serve right-sized
   modern formats, and remove render-blocking resources so the main content paints
   sooner.

3. **Fix INP — input responsiveness.** Break up long tasks, yield to the main thread,
   and defer non-critical JavaScript so taps and clicks respond within the budget.

4. **Fix CLS — layout stability.** Reserve space for images, embeds, and late-loading
   content with explicit dimensions so nothing jumps as the page settles.

5. **Use the service worker for perceived speed.** A [cached app shell](/guides/offline/)
   makes repeat launches feel instant — the PWA's structural advantage over a plain
   site. The caching model is in the
   [service worker reference](/reference/service-worker/).

6. **Re-measure and lock it in.** Confirm the change moved the metric, then add a
   budget (Lighthouse CI or a Web Vitals check) so a regression is caught before it
   ships.

</Steps>

## Perceived vs. measured speed

The numbers matter, but so does feel. Skeleton screens, optimistic UI, and an
instant-launching cached shell make an app *feel* fast even when a network request is
still in flight — and a fast-feeling app keeps users where a technically-fast-but-janky
one loses them.

## Where to go next

- [Offline strategies](/guides/offline/) — caching is half of perceived performance.
- [Advanced](/guides/advanced/) — production concerns once the basics are tuned.
- [Core Web Vitals reference](/reference/performance/core-web-vitals/) — the metric definitions in full.

← Back to the [Guides](/guides/) overview.