Skip to main content
AC
Quality & Security5.1 KBMIT licensed

performance-optimization

Rewritten from patterns in addyosmani/agent-skills (MIT)

Profile-first performance work: find the real bottleneck, fix it, prove the improvement. Use when Core Web Vitals or load times miss targets, users report slowness, a change may have regressed performance, or perf budgets exist. Not for adding the telemetry that detects slowness: use observability-and-instrumentation. Not for general debugging of wrong behavior: use systematic-debugging.

  • performance
  • optimization

SKILL.md

Performance Optimization

Measure before optimizing. Performance work without measurement is guessing, and guessing produces complexity without improving what users feel. Do not optimize before you have evidence of a problem.

Workflow

  1. Measure. Establish a baseline with numbers. Synthetic (Lighthouse, DevTools performance trace) for reproducible comparison and CI. RUM (web-vitals library, CrUX) to validate real users actually improved. Backend: response-time logging, APM, query timing. Both kinds, not one.
  2. Identify. Find the actual bottleneck, not the assumed one. Use the routing table below.
  3. Fix. Address that specific bottleneck. Code patterns for the common anti-patterns are in references/anti-patterns.md, read it when applying a fix.
  4. Verify. Measure again under the same conditions. Confirm the number moved and tests still pass.
  5. Guard. Add a CI budget check or monitoring so it cannot silently regress.

Where to look, by symptom

SymptomLikely causeFirst measurement
Slow first loadLarge bundle, render-blocking CSS/JSBundle analysis, network waterfall
Slow TTFBServer work, DNS, no edge/keep-aliveWaterfall timing breakdown, backend profile
Slow LCPOversized hero image, blocking resources, slow serverWaterfall, image sizes, fetchpriority
High CLSImages without dimensions, late content, font swapLayout shift attribution
Poor INP / frozen UILong main-thread tasks, giant DOM updatesPerformance trace, tasks over 50ms
Form input lagRe-renders, controlled-component overheadReact profiler
Slow after navigationRequest waterfalls, N+1 fetchesAPI timing, request graph
One endpoint slowN+1 queries, missing indexDB query log with timing
All endpoints slowPool exhaustion, CPU, memoryHost and pool metrics
IntermittentLock contention, GC pauses, external depsTraces across the stack

Targets and budgets

Core Web Vitals "good": LCP <= 2.5s, INP <= 200ms, CLS <= 0.1.

Set budgets and enforce them in CI (bundle-size check plus Lighthouse CI). Sane defaults: initial JS under 200KB gzipped, CSS under 50KB, above-the-fold images under 200KB each, API p95 under 200ms, Lighthouse performance 90+. Adjust to your product, but write them down and gate on them.

Verification

Run the same measurement before and after the fix, same conditions, same hardware profile. Expect: the targeted metric improved by a stated amount, no other budget regressed, and the test suite passes. If the number did not move, the bottleneck was misidentified: revert the change and go back to step 2 rather than stacking more "optimizations".

Good vs Bad

Bad: "The list page feels slow, I added React.memo to every component and useMemo everywhere." No measurement, shotgun fix, added complexity, unknown effect.

Good: "Profile showed 1.8s in the tasks endpoint; query log revealed one owner lookup per task (N+1, 300 queries). Switched to a join: p95 went 1.9s to 210ms. Added a query-count assertion to the endpoint test."

Completion checklist

  • [ ] Before and after numbers recorded, same measurement conditions
  • [ ] Specific bottleneck named and addressed
  • [ ] Core Web Vitals within "good", or documented why not yet
  • [ ] Bundle size did not grow unnoticed
  • [ ] No new N+1 or unpaginated queries introduced
  • [ ] Budget enforced in CI or a regression guard added
  • [ ] Existing tests pass

Any box unchecked: not done. Fix or say so.

Footguns

  • Optimizing on your machine. Dev hardware on fiber hides everything. Fix: throttled profiles and RUM from representative devices and networks.
  • Averages. A 200ms average with a 4s p99 means 1% of users suffer while your dashboard smiles. Fix: histograms, read p95/p99.
  • Memoizing everything. React.memo and useMemo everywhere adds comparison overhead and complexity for unmeasured gain. Fix: profile, memoize the proven-expensive paths only.
  • Trusting the framework. Frameworks cannot fix N+1 queries or a 2MB bundle you imported. Fix: measure your app, not the framework's marketing.

Red Flags

Stop if you hear yourself think any of these:

  • "This optimization is obvious, no need to profile"
  • "It's fast on my machine"
  • "We'll optimize later"
  • "Users won't notice 100ms"
  • "The framework handles performance"

Every one of these means you are about to guess. The rule is absolute: no fix without a baseline number, no "done" without an after number. Fix obvious anti-patterns (N+1, unpaginated endpoints, undimensioned images) as you write code; defer everything else until measured.

Reference files

More in Quality & Security

All skills