Developer pack
Claude SkillUpdated today
Performance Optimization Workflow
Runs performance work as a measured loop: baseline, find the real bottleneck, fix one thing, re-measure, and revert anything inside the noise.
What it does
Applies a five-step protocol to slow pages and slow APIs: measure a baseline, map the symptom to the actual bottleneck, fix that one thing, re-measure with identical methodology, and add a CI budget so the win survives. Covers Core Web Vitals targets, the standard backend killers (N+1 queries, unbounded fetches, missing caching), and the discipline most performance work skips: reverting changes that do not beat run-to-run variance.
When to use
- ✓A page or endpoint is slow and nobody has profiled it yet
- ✓Core Web Vitals fell out of the "Good" band and you need a prioritized route back
- ✓Reviewing an optimization PR and deciding whether the claimed win is real or inside the noise
When not to use
- ✗No measured evidence of a problem exists; premature optimization adds complexity that costs more than it returns
- ✗The issue is specifically React render behavior — react-performance-reviewer carries the framework-level rule set
Install
Download the .zip, then unzip into your Claude skills folder.
mkdir -p ~/.claude/skills
unzip ~/Downloads/performance-optimization-workflow.zip -d ~/.claude/skills/
# Restart Claude Code session.
# Skill is now available — Claude will use it when relevant.SKILL.md
SKILL.md
---
name: performance-optimization-workflow
description: Use when a page or API is slow, Core Web Vitals need improvement, an N+1 query pattern is suspected, or an optimization claim needs verification. Triggers on "why is this slow", "improve LCP", "this endpoint takes seconds", "did this optimization actually work".
---
# Performance Optimization Workflow
Measure before optimizing; performance work without measurement is guessing. Every engagement runs the same loop — Measure, Identify, Fix, Verify, Guard — and the loop only moves forward on evidence.
## 1. Measure a baseline
Two kinds of measurement, and both matter. Synthetic (Lighthouse, the DevTools Performance panel) is reproducible and belongs in CI. Real-user monitoring (the web-vitals library, CrUX) tells you whether actual users on actual networks got faster, which is the only definition of success that counts. On the backend, response-time logging and query timing fill the same role. Record the baseline numbers and the exact methodology; the verify step reuses both.
Reference targets for the web vitals:
| Metric | Good | Needs improvement | Poor |
| --- | --- | --- | --- |
| LCP | up to 2.5s | up to 4.0s | over 4.0s |
| INP | up to 200ms | up to 500ms | over 500ms |
| CLS | up to 0.1 | up to 0.25 | over 0.25 |
## 2. Map the symptom to the bottleneck
Slow LCP points at large images or render-blocking resources. High CLS points at images without dimensions or content that loads late and pushes the page around. Poor INP points at heavy main-thread JavaScript. On the backend: a slow list endpoint is an N+1 query or a missing index until proven otherwise; steady memory growth is a leaked reference or an unbounded cache; CPU spikes are synchronous heavy computation. Profile to confirm — the assumed bottleneck and the actual one disagree often enough to make guessing expensive.
## 3. Fix exactly one thing
The recurring offenders, in rough order of payoff: N+1 queries (replace the loop with a join or an include), unbounded fetches (paginate with a sane limit), unoptimized images (dimensions set, lazy-loaded below the fold, fetchpriority high on the LCP image), oversized bundles (dynamic imports and route-level code splitting), and missing caching (TTLs on frequently-read rarely-changed data, Cache-Control on static assets and API responses). One change at a time — bundle three fixes and you cannot attribute the result to any of them.
## 4. Verify: keep or revert
Re-measure with the same tools, conditions, and methodology as the baseline. Then apply the decision table without negotiation:
| Result vs. baseline | Action |
| --- | --- |
| Beats the threshold, tests green | Keep; commit with the before and after numbers |
| Within run-to-run variance | Revert |
| Worse | Revert |
| Faster, but a test now fails | Revert; that is a regression wearing a disguise |
Neutral is a revert, not a keep — unmeasured complexity accumulates forever. A 3% gain inside 5% variance is not a gain. Log every attempt including the reverted ones, so the next person does not re-try a failed idea with fresh confidence.
## 5. Guard the win
A fix without a guard decays. Set budgets and enforce them in CI with Lighthouse CI or a bundle-size check: initial JavaScript under 200KB gzipped, CSS under 50KB, above-the-fold images under 200KB each, API p95 under 200ms, Lighthouse performance score at or above 90. Adjust the numbers to the product; the point is that a regression fails a build instead of waiting for a user complaint.
## Red flags
- Optimization proposed without profiling data behind it
- A list endpoint with no pagination
- Images without dimensions or lazy loading
- Liberal React.memo and useMemo sprinkled as a reflex rather than from a profile
- A claimed win that required changing or deleting tests
- Multiple optimizations in one PR, making attribution impossible
- A "fix" kept because it felt faster, with no before and after numbers
Example prompts
Once installed, try these prompts in Claude:
- Our dashboard endpoint takes 4 seconds. Walk me through finding the bottleneck before we touch any code.
- Mobile LCP is 4.2s. Give me the measured path back under 2.5s, in priority order.
- Review this optimization PR: did it beat the baseline, or is the improvement inside run-to-run variance?
Recent changes
- Aug 4, 2026New skill: the measure/identify/fix/verify/guard loop with Core Web Vitals targets, N+1 and caching anti-patterns, and CI performance budgets.