Skip to content
Published on

Performance & Core Web Vitals 2025 — LCP, CLS, INP, RUM, Image/Font/JS Optimization, Edge, CDN, HTTP/3 (S6 E6)

Authors

Prologue — performance is not a feature

A common misconception: "performance optimization is post-launch tuning." In 2025, reality says otherwise.

  • Google search ranking incorporates Core Web Vitals (since 2021).
  • Ecommerce research: +1% conversion per 0.1s LCP improvement (Amazon, Booking).
  • INP became an official metric in 2024, kicking off a responsiveness race.
  • Korean users live on subway 5G, low-power mode — the tail matters.

"Performance isn't a feature. It's the precondition for every feature."

Good AI, good UX, great motion — all worthless if slow. This is the 2025 frontline guide.


1. Core Web Vitals 2025 — the three numbers

LCP (Largest Contentful Paint)

  • When the largest viewport element renders.
  • Good ≤ 2.5s, Needs Improvement ≤ 4s, Poor > 4s.
  • Usually a hero image or text block.

CLS (Cumulative Layout Shift)

  • Cumulative viewport shift score.
  • Good ≤ 0.1, Needs ≤ 0.25, Poor > 0.25.
  • Usual offenders: images without dimensions, ads, font swap.

INP (Interaction to Next Paint) — replaced FID in 2024

  • From input to next paint.
  • Good ≤ 200ms, Needs ≤ 500ms, Poor > 500ms.
  • Detects slow JS and main-thread blocking; covers the entire page lifetime (unlike FID).

Measurement conventions

  • p75 percentile — matches most-user experience.
  • Real users, 28-day rolling (CrUX).
  • Mobile vs desktop split.

Supporting metrics

  • FCP target 1.8s, TTFB target 0.8s.
  • TTI is legacy — INP replaced it.

2. RUM vs synthetic — what to measure

Synthetic

  • Controlled lab (Lighthouse, WebPageTest, SpeedCurve).
  • Pros: reproducible, regression detection.
  • Cons: diverges from real users.

RUM

  • Real browsers (Vercel Speed Insights, Datadog RUM, New Relic, Sentry, CrUX).
  • Pros: truth.
  • Cons: noisy, outliers dominate small samples.

Do both

  • Lighthouse in CI for regressions.
  • RUM in production for truth.
  • CrUX monthly review for competitive benchmarking.

CrUX (Chrome UX Report)

Anonymized Chrome opt-in data, monthly aggregate. Powers PageSpeed Insights and is available in BigQuery.


3. Critical rendering path

Browser pipeline: Network → Parse HTML → CSSOM → Render Tree → Layout → Paint → Composite.

Common bottlenecks

  • Render-blocking CSS.
  • Render-blocking JS.
  • Font swap period (FOIT/FOUT).

2025 standard techniques

  1. Critical CSS inlined for above-the-fold.
  2. <script defer> / async — stop blocking HTML parse.
  3. <img fetchpriority="high"> on the LCP image.
  4. <link rel="preconnect"> for third-party origins.
  5. <link rel="preload"> for critical fonts/hero images.

4. JS bundle diet

Good sizes in 2025:

  • Initial < 170kb gzipped, per route < 50kb.
  • Mobile parse/execute cost is real.

Bundler landscape

  • esbuild (Go), swc (Rust, inside Next.js), Rollup (libraries), Turbopack (Next 15 default), Vite (Rollup underneath), Rspack (Rust, Webpack-compatible), Bun (runtime + bundler).

Usual offenders

  • momentdate-fns or dayjs.
  • lodash full → per-function import.
  • react-icons → raw SVG.
  • CommonJS packages that block tree-shaking — mark "sideEffects": false.
  • Dynamic import for heavy widgets (charts, modals).
  • Polyfill bloat — target Baseline 2024.
  • Runtime CSS-in-JS → zero-runtime (Linaria, Vanilla Extract, Pigment) or Tailwind / CSS Modules.

5. Image optimization — the LCP lever

Format

  • AVIF (best compression) + WebP + JPEG fallback. SVG for vectors.

Responsive <picture> and <img srcset sizes>

Next.js <Image>

import Image from 'next/image'
<Image src="/hero.jpg" width={1200} height={600} priority placeholder="blur" blurDataURL={blur} alt="Hero" />

Auto AVIF/WebP, responsive srcset, lazy by default (priority for LCP), prevents CLS.

Tips

  • Always specify width/height.
  • Lazy + priority combo.
  • LCP image: preload + fetchpriority="high".
  • Hero art worth inlining as SVG/data-URL for small files.

6. Font optimization

font-display

  • swap — fallback first (fast, CLS risk).
  • optional — if not loaded in 100ms, keep fallback (no CLS).
  • fallback — in between.

size-adjust + ascent-override

Match fallback metrics to web font — dramatically reduces CLS.

Subsetting

Korean/Japanese/Chinese fonts are multi-MB. Subset to KS X 1001 2,350 / JIS core / etc. Use Subfont or Glyphhanger to automate.

Variable fonts

One file, every weight/width. Pretendard Variable (Korean), Inter/Geist (Latin).

Pretendard Variable + Noto Sans KR fallback, font-display: swap, size-adjust on fallback.


7. Caching

HTTP cache

  • Cache-Control: public, max-age=31536000, immutable for hashed assets.
  • no-cache for always-validate.
  • no-store never.
  • ETag / Last-Modified for conditional requests.
  • stale-while-revalidate for smooth rotation.

Next.js 15 caching (redesigned)

Request memoization, Data Cache, Full Route Cache, Router Cache. 2025+: explicit use cache directive opts in.

Service Worker

Offline, app-shell, cache-first for assets (Workbox). PWA revival on iOS as restrictions ease.

Edge caching

CDN-level stale-while-revalidate. ISR remains the Next.js cornerstone.


8. Edge, CDN, HTTP/3

Roles

Geographic proximity, origin offload, TLS/HTTP/3/compression.

Players

Cloudflare (best balance), Vercel Edge, Fastly (VCL), AWS CloudFront, Netlify Edge. Korea: Toast KRP, NAVER Cloud CDN, KT Olleh CDN.

Edge functions

Cloudflare Workers, Vercel Edge, Deno Deploy, Fastly Compute@Edge. Minimal cold start (V8 isolates). Use for A/B, auth, rate limit, i18n routing.

HTTP/3 (QUIC)

UDP, no head-of-line blocking, 0-RTT, TLS 1.3. Default on most CDNs. Huge win on mobile and unstable networks — especially Korean subway 5G.


9. INP optimization

Long tasks (>50ms) on the main thread break responsiveness.

  1. Debounce / throttle search and scroll handlers.
  2. Scheduler API: scheduler.postTask(() => heavy(), { priority: 'background' }).
  3. useDeferredValue / useTransition in React 18+.
  4. Web Workers for heavy computation.
  5. Virtualization (react-window, TanStack Virtual) for long lists.
  6. Code splitting for features used occasionally.

Measure with Chrome DevTools Performance → INP, Long Task API in production.


10. Tooling

  • Vercel Speed Insights — zero-config RUM on Vercel.
  • Datadog RUM / New Relic — enterprise-grade.
  • CrUX Dashboard — free, origin-level.
  • PageSpeed Insights — Lighthouse + CrUX combined.
  • WebPageTest — highest-fidelity synthetic.

11. Practical checklist

Project setup

  • Framework Image component, font-display: swap + size-adjust, Critical CSS.
  • Bundle Analyzer, Lighthouse CI with thresholds (LCP<2.5s, CLS<0.1, INP<200ms).
  • RUM (Vercel Speed Insights or self-hosted).

Pre-release

  • LCP cause analysis (DevTools Performance insights), INP handler review, image dimensions, bundle under target, font preload, 3G Fast emulation.

Post-release

  • RUM p75 trends, incident rollback, weekly performance review.

12. Advanced patterns (2025)

  • Partial Pre-Rendering (PPR) — Next.js 15 static shell + dynamic holes.
  • Islands — Astro: static + JS islands only.
  • Qwik resumability — near-zero initial JS.
  • Bun / Deno — faster startup for SSR.
  • Turbopack — Next.js 15 default.
  • Server streaming with RSC + Suspense.

12-item checklist

  1. CWV p75 tracked via RUM?
  2. LCP<2.5s, CLS<0.1, INP<200ms at p75?
  3. LCP image has priority + fetchpriority="high"?
  4. All images have explicit width/height?
  5. Fonts use font-display + size-adjust?
  6. Initial bundle < 170kb, route < 50kb?
  7. Dynamic import for heavy code?
  8. CDN + edge caching configured?
  9. HTTP/3 enabled?
  10. Lighthouse CI catches regressions?
  11. RUM operated in production?
  12. Korean mobile/subway network tested?

10 anti-patterns

  1. Shipping without measuring real users.
  2. Optimizing for Lighthouse score but not p75 RUM.
  3. Unsized images (CLS bomb).
  4. font-display: block (FOIT hides content).
  5. Giant moment.js / lodash full imports.
  6. Runtime CSS-in-JS in hot paths.
  7. Forgetting <link rel="preload"> on LCP image.
  8. Treating INP like FID (single-interaction testing).
  9. Sampling RUM too low to detect tail regressions.
  10. Ignoring Asian/Korean network realities.

Next episode

Season 6 Episode 7: Accessibility & Internationalization 2025 — WCAG 2.2, EU Accessibility Act, ARIA, next-intl, Korean/Japanese typography, RTL.

"A fast product is a good product. A slow product is a non-existent product."

— End of Performance & Core Web Vitals.