Astro is fast by default, but you can still ship a slow Astro site if you're careless. Here's the systematic approach we use to hit 95+ Lighthouse on production Astro sites.

Partial hydration discipline

Astro's superpower is shipping zero JavaScript by default. Every interactive component you add costs you JavaScript. Be ruthless:

  • Use client:idle over client:load wherever possible — defer hydration until the browser is idle.
  • Use client:visible for below-fold components — they only hydrate when they enter the viewport.
  • Audit your bundle. Look at what's in _astro/*.js in the build output. Remove anything you don't actually need.

Image strategy

This is where 80% of LCP problems live. Astro's built-in <Image> component handles most of it for you:

  • Set explicit width and height to prevent CLS.
  • Use format="avif" with WebP fallback. Avoid JPG/PNG in production output.
  • For the LCP image specifically: loading="eager", fetchpriority="high", and a <link rel="preload"> in the head.
  • For below-fold: loading="lazy".
  • Use srcset and sizes for responsive images. Don't serve desktop-sized images to phones.

Font strategy

Fonts are the second-biggest cause of CLS:

  • Self-host fonts whenever possible. Don't depend on Google Fonts CDN.
  • Use font-display: swap for fallback rendering.
  • Set size-adjust on @font-face declarations to minimise the FOUT shift.
  • Preload the primary font in the document head.
  • Subset fonts to only the characters you actually use.

CSS strategy

Astro inlines critical CSS automatically. Don't fight it. Keep your global CSS small. Use scoped styles for component-specific CSS.

JavaScript audit

Look at your network panel on a production build. The JavaScript you should see:

  • Astro's tiny runtime (a few KB).
  • Any explicitly hydrated component bundles.

If you see more, find out why. Common culprits: analytics scripts, third-party widgets, framework code you imported but aren't using.

Third-party scripts

Every third-party script is a performance liability. The rules we follow:

  • Analytics: load with async after page load. Or replace with a lighter alternative (Plausible, Fathom, server-side via Cloudflare).
  • Chat widgets: load only on pages that need them, and only after user interaction.
  • Ad scripts: there's no good way to make these fast. Either accept the performance hit or remove them.

Edge hosting

Astro pairs naturally with edge hosting. Deploy on Cloudflare Pages, Vercel Edge, or Netlify Edge. The TTFB win is meaningful — usually 200-400ms globally.

Caching strategy

  • Static pages: cache forever, invalidate on deploy.
  • API responses: use stale-while-revalidate for ones that can tolerate brief staleness.
  • Images: aggressive long-term caching with content-hash filenames.

Measurement

Lighthouse in CI catches regressions. Real-user monitoring (Cloudflare Web Analytics, Vercel Speed Insights, SpeedCurve) catches what Lighthouse misses. Set budgets and alert when you exceed them.

The 95+ checklist

Before you ship, verify:

  • LCP image is preloaded and properly sized.
  • JavaScript bundle is under 100KB for the homepage.
  • No layout shift on font load (test with throttled network).
  • Third-party scripts load after the page is interactive.
  • All images have explicit dimensions.
  • Critical CSS is inlined.

Hit those, and 95+ on Lighthouse is the default outcome.