Thresholds (p75 field, p98 for INP)

Metric Good NI Poor
TTFB — Time to First Byte ≤ 800ms ≤ 1800ms > 1800ms
FCP — First Contentful Paint ≤ 1800ms ≤ 3000ms > 3000ms
LCP — Largest Contentful Paint ≤ 2500ms ≤ 4000ms > 4000ms
INP — Interaction to Next Paint ≤ 200ms ≤ 500ms > 500ms
CLS — Cumulative Layout Shift ≤ 0.1 ≤ 0.25 > 0.25
TBT — Total Blocking Time ≤ 200ms ≤ 600ms > 600ms

Fix quick-map

ProblemFirst checksCommon fixes
High TTFB Server timing, CDN cache, redirects Edge cache, query optimization, Early Hints
High LCP LCP element in trace, priority, lazy? preload + fetchpriority, dimensions, AVIF, no client-only hero
High INP Long tasks, interaction in Performance yield, workers, defer hydration, cut third-party JS
High CLS Layout shift regions in DevTools width/height, aspect-ratio, font fallbacks, ad slots
High TBT (lab) Main thread flame chart Same as INP — split tasks, less sync JS on load

API snippets

import { onLCP, onINP, onCLS } from 'web-vitals';
onLCP(console.log);
onINP(console.log);
onCLS(console.log);

// Long tasks
new PerformanceObserver((l) => {
  l.getEntries().forEach((e) => console.log('long', e.duration));
}).observe({ type: 'longtask', buffered: true });

// Yield
await scheduler.yield?.() ?? new Promise(r => setTimeout(r, 0));

Resource hints

<link rel="preconnect" href="https://cdn.example" crossorigin>
<link rel="preload" href="/hero.avif" as="image" fetchpriority="high">
<link rel="modulepreload" href="/app.js">
<link rel="prefetch" href="/next-page.js">

CSS performance

.item {
  content-visibility: auto;
  contain-intrinsic-size: 0 120px;
  contain: layout style paint;
}
/* Animate only: */
.panel { transform: translateY(0); opacity: 1; }

Live on this page

TTFB
FCP
LCP
INP
CLS