Back to React
React
medium
mid

How do you debug performance issues in a React application?

Start with RUM (web-vitals: LCP, INP, CLS, p75 in prod). Reproduce in dev → React DevTools Profiler shows which components rendered, why, and how long. Chrome Performance panel for main-thread tasks. Lighthouse for asset/CSS issues. Memory panel for leaks. Bundle analyzer for size. Don't optimize without measurement.

5 min read·~10 min to think through

Step 1 — measure prod

You can't optimize what you don't measure. RUM in production beats lab in dev:

js
import { onLCP, onINP, onCLS } from "web-vitals";
onLCP(({ value }) => beacon({ name: "LCP", value }));
onINP(({ value }) => beacon({ name: "INP", value }));
onCLS(({ value }) => beacon({ name: "CLS", value }));

Track p75 per route. Set budgets (LCP < 2.5s, INP < 200ms, CLS < 0.1). Regression alerts.

Step 2 — reproduce

Get a reliable local repro. CPU throttle (4x), network throttle (Slow 4G). What feels jank-free on a M1 MacBook can be unusable on a low-end Android.

Step 3 — React DevTools Profiler

  • Record an interaction.
  • Flamegraph shows which components rendered and how long.
  • Ranked shows expensive renders sorted.
  • "Why did this render?" hover tooltip → state/props/parent.
  • Highlight Updates setting in DevTools shows visually which nodes re-render.

What to look for:

  • Unexpected re-renders (parent state change cascading).
  • A single slow component (heavy compute, big list).
  • Context fan-out (every consumer re-renders).

Step 4 — Chrome Performance panel

  • Record a slow interaction.
  • Look at the main thread: long tasks (> 50ms) flagged.
  • Identify scripts / handlers eating time.
  • Bottom-up view shows where ms went.

INP regressions are usually visible here as a long task in an event handler.

Step 5 — Lighthouse

  • LCP element flagged.
  • Render-blocking resources.
  • Unused CSS / JS.
  • Image opportunities.

Great for the "initial load" category. Less useful for runtime / INP.

Step 6 — Bundle analyzer

bash
ANALYZE=true next build
# or webpack-bundle-analyzer / source-map-explorer / vite-plugin-visualizer

Identify the heaviest dependencies. Common offenders: moment (use date-fns), lodash full (use lodash-es per-import or just JS), big icon sets imported unsplit.

Step 7 — Memory panel

For leaks: heap snapshot, do the suspected leaky thing N times, heap snapshot again, compare. Detached DOM report finds zombie nodes.

Step 8 — Targeted fixes by category

SymptomFix
Slow LCPHero image optimization, RSC/SSR, fewer render-blocking resources.
High INPBreak long tasks, transitions, Workers, debounce.
Many re-rendersSplit context, memoize stable callbacks, fix unstable prop refs.
Long list jankVirtualize.
Slow filter/sortuseMemo, useDeferredValue, Web Worker.
Bundle bloatCode splitting, dynamic imports, tree-shake, swap heavy deps.
Memory growthCleanup in effects, AbortController, bounded caches.

Anti-patterns

  • Sprinkling useMemo without profiling.
  • Optimizing the first thing you see in DevTools without confirming it's the bottleneck.
  • Trusting lab-only metrics on a dev machine.
  • Ignoring p99 / mobile because p50 looks fine.

Workflow I follow

  1. Get RUM data.
  2. Identify worst route + metric.
  3. Reproduce with CPU/network throttling.
  4. Profile in DevTools.
  5. Hypothesize fix.
  6. Implement.
  7. Measure delta.
  8. Ship.
  9. Watch prod RUM.

Interview framing

"Start with RUM (web-vitals p75 in prod) — without it you're guessing. Then reproduce with CPU + network throttling. React DevTools Profiler shows render flamegraphs and 'why did this render'; highlights unexpected re-renders. Chrome Performance panel for main-thread long tasks (INP). Lighthouse for initial load issues. Memory panel for leaks. Bundle analyzer for size. Targeted fix by category — context fan-out, unmemoized callbacks, long lists, big bundle, etc. Always measure delta before/after; many memoization PRs don't actually move metrics. And optimize for mobile / low-end, not the M1 MacBook."

Follow-up questions

  • What's your default profiling toolkit?
  • Walk through a recent perf debug.
  • How do you decide where to start?

Common mistakes

  • Optimizing without measuring.
  • Trusting dev machine metrics.
  • Stopping at the first 'fix' without delta measurement.

Performance considerations

  • The whole topic.

Edge cases

  • Profiler overhead affects measurements.
  • Dev vs prod build differences.
  • Strict Mode double-mount in dev.

Real-world examples

  • Vercel's perf insights, web.dev case studies, React docs profiling guide.

Senior engineer discussion

Seniors articulate a measurement-first workflow with RUM, repro, profile, hypothesize, measure delta, and ship; they avoid optimization PRs that lack before/after numbers.

Related questions