.fyi
SkillsMCPPluginsSubagents

Browse by category

DevOps & CI/CD SkillsProductivity & Workflow SkillsOther SkillsProduct & Project Management SkillsDocumentation & Knowledge SkillsCode Review & Refactor SkillsBackend & APIs SkillsAgent Meta & Communication SkillsResearch SkillsSecurity SkillsUX UI & Design SkillsTesting & QA SkillsSee all →

Every Claude Code skill, MCP server, plugin and subagent in one directory. Searchable, comparable, and one command from installed. Live stats from GitHub, npm and PyPI.

We're on Product HuntYour agent's app storeCheck it out →
Agent SkillsMCP ServersPluginsSubagentsCoding Agents
CollectionsOfficial publishersGlossaryFAQBlogSearchSavedFeedback
PrivacyTermsllms.txtSitemap

made with ♥ · © 2026 aaaa.fyi

Independent project · real data from public registries

…/agent-skills/performance-optimization
home/skills/addyosmani/agent-skills/performance-optimization
addyosmani avatar

performance-optimization

byaddyosmani· 31 skills

Installs

16k

Stars

80k

Forks

8.7k

Category

Backend & APIs

View on GitHub

TL;DR

Optimizes application performance across frontend, backend, queries, and databases. Use when performance requirements exist, when you suspect performance regressions, when Core Web Vitals or load times need improvement, when N+1 query patterns need fixing, or when profiling reveals bottlenecks.

How to install performance-optimization?

addyosmani/agent-skills/performance-optimization
$npx -y skills add addyosmani/agent-skills --skill performance-optimization

Installs into the current project.

›Prefer a prompt? Paste this to your agent

Use this skill

Run `npx skills use "https://github.com/addyosmani/agent-skills" --skill "addyosmani/agent-skills/performance-optimization"` and follow the generated skill instructions now. Read its complete output, redirecting it to a temporary file first if necessary. Resolve relative paths from the supporting-files directory it provides.

Use the whole pack

Use the skills in "https://github.com/addyosmani/agent-skills" that are relevant to the current task. Run `npx skills add "https://github.com/addyosmani/agent-skills"` and select the relevant skills, then follow their instructions.

Files · 1

View on GitHub
SKILL.md
1# Performance Optimization
2 
3## Overview
4 
5Measure before optimizing. Performance work without measurement is guessing — and guessing leads to premature optimization that adds complexity without improving what matters. Profile first, identify the actual bottleneck, fix it, measure again. Optimize only what measurements prove matters.
6 
7## When to Use
8 
9- Performance requirements exist in the spec (load time budgets, response time SLAs)
10- Users or monitoring report slow behavior
11- Core Web Vitals scores are below thresholds
12- You suspect a change introduced a regression
13- Building features that handle large datasets or high traffic
14 
15**When NOT to use:** Don't optimize before you have evidence of a problem. Premature optimization adds complexity that costs more than the performance it gains.
16 
17## Core Web Vitals Targets
18 
19| Metric | Good | Needs Improvement | Poor |
20|--------|------|-------------------|------|
21| **LCP** (Largest Contentful Paint) | ≤ 2.5s | ≤ 4.0s | > 4.0s |
22| **INP** (Interaction to Next Paint) | ≤ 200ms | ≤ 500ms | > 500ms |
23| **CLS** (Cumulative Layout Shift) | ≤ 0.1 | ≤ 0.25 | > 0.25 |
24 
25## The Optimization Workflow
26 
27```
281. MEASURE → Establish baseline with real data
292. IDENTIFY → Find the actual bottleneck (not assumed)
303. FIX → Address the specific bottleneck
314. VERIFY → Measure again; keep or revert
325. GUARD → Add monitoring or tests to prevent regression
33```
34 
35### Step 1: Measure
36 
37Two complementary approaches — use both:
38 
39- **Synthetic (Lighthouse, DevTools Performance tab):** Controlled conditions, reproducible. Best for CI regression detection and isolating specific issues.
40- **RUM (web-vitals library, CrUX):** Real user data in real conditions. Required to validate that a fix actually improved user experience.
41 
42**Frontend:**
43```bash
44# Synthetic: Lighthouse in Chrome DevTools (or CI)
45# Chrome DevTools → Performance tab → Record
46# Chrome DevTools MCP → Performance trace
47 
48# RUM: Web Vitals library in code
49import { onLCP, onINP, onCLS } from 'web-vitals';
50 
51onLCP(console.log);
52onINP(console.log);
53onCLS(console.log);
54```
55 
56**Backend:**
57```bash
58# Response time logging
59# Application Performance Monitoring (APM)
60# Database query logging with timing
61 
62# Simple timing
63console.time('db-query');
64const result = await db.query(...);
65console.timeEnd('db-query');
66```
67 
68### Where to Start Measuring
69 
70Use the symptom to decide what to measure first:
71 
72```
73What is slow?
74├── First page load
75│ ├── Large bundle? --> Measure bundle size, check code splitting
76│ ├── Slow server response? --> Measure TTFB in DevTools Network waterfall
77│ │ ├── DNS long? --> Add dns-prefetch / preconnect for known origins
78│ │ ├── TCP/TLS long? --> Enable HTTP/2, check edge deployment, keep-alive
79│ │ └── Waiting (server) long? --> Profile backend, check queries and caching
80│ └── Render-blocking resources? --> Check network waterfall for CSS/JS blocking
81├── Interaction feels sluggish
82│ ├── UI freezes on click? --> Profile main thread, look for long tasks (>50ms)
83│ ├── Form input lag? --> Check re-renders, controlled component overhead
84│ └── Animation jank? --> Check layout thrashing, forced reflows
85├── Page after navigation
86│ ├── Data loading? --> Measure API response times, check for waterfalls
87│ └── Client rendering? --> Profile component render time, check for N+1 fetches
88└── Backend / API
89 ├── Single endpoint slow? --> Profile database queries, check indexes
90 ├── All endpoints slow? --> Check connection pool, memory, CPU
91 └── Intermittent slowness? --> Check for lock contention, GC pauses, external deps
92```
93 
94### Step 2: Identify the Bottleneck
95 
96Common bottlenecks by category:
97 
98**Frontend:**
99 
100| Symptom | Likely Cause | Investigation |
101|---------|-------------|---------------|
102| Slow LCP | Large images, render-blocking resources, slow server | Check network waterfall, image sizes |
103| High CLS | Images without dimensions, late-loading content, font shifts | Check layout shift attribution |
104| Poor INP | Heavy JavaScript on main thread, large DOM updates | Check long tasks in Performance trace |
105| Slow initial load | Large bundle, many network requests | Check bundle size, code splitting |
106 
107**Backend:**
108 
109| Symptom | Likely Cause | Investigation |
110|---------|-------------|---------------|
111| Slow API responses | N+1 queries, missing indexes, unoptimized queries | Check database query log |
112| Memory growth | Leaked references, unbounded caches, large payloads | Heap snapshot analysis |
113| CPU spikes | Synchronous heavy computation, regex backtracking | CPU profiling |
114| High latency | Missing caching, redundant computation, network hops | Trace requests through the stack |
115 
116### Step 3: Fix Common Anti-Patterns
117 
118#### N+1 Queries (Backend)
119 
120```typescript
121// BAD: N+1 — one query per task for the owner
122const tasks = await db.tasks.findMany();
123for (const task of tasks) {
124 task.owner = await db.users.findUnique({ where: { id: task.ownerId } });
125}
126 
127// GOOD: Single query with join/include
128const tasks = await db.tasks.findMany({
129 include: { owner: true },
130});
131```
132 
133#### Unbounded Data Fetching
134 
135```typescript
136// BAD: Fetching all records
137const allTasks = await db.tasks.findMany();
138 
139// GOOD: Paginated with limits
140const tasks = await db.tasks.findMany({
141 take: 20,
142 skip: (page - 1) * 20,
143 orderBy: { createdAt: 'desc' },
144});
145```
146 
147#### Missing Image Optimization (Frontend)
148 
149```html
150<!-- BAD: No dimensions, no format optimization -->
151<img src="/hero.jpg" />
152 
153<!-- GOOD: Hero / LCP image — art direction + resolution switching, high priority -->
154<!--
155 Two techniques combined:
156 - Art direction (media): different crop/composition per breakpoint
157 - Resolution switching (srcset + sizes): right file size per screen density
158-->
159<picture>
160 <!-- Mobile: portrait crop (8:10) -->
161 <source
162 media="(max-width: 767px)"
163 srcset="/hero-mobile-400.avif 400w, /hero-mobile-800.avif 800w"
164 sizes="100vw"
165 width="800"
166 height="1000"
167 type="image/avif"
168 />
169 <source
170 media="(max-width: 767px)"
171 srcset="/hero-mobile-400.webp 400w, /hero-mobile-800.webp 800w"
172 sizes="100vw"
173 width="800"
174 height="1000"
175 type="image/webp"
176 />
177 <!-- Desktop: landscape crop (2:1) -->
178 <source
179 srcset="/hero-800.avif 800w, /hero-1200.avif 1200w, /hero-1600.avif 1600w"
180 sizes="(max-width: 1200px) 100vw, 1200px"
181 width="1200"
182 height="600"
183 type="image/avif"
184 />
185 <source
186 srcset="/hero-800.webp 800w, /hero-1200.webp 1200w, /hero-1600.webp 1600w"
187 sizes="(max-width: 1200px) 100vw, 1200px"
188 width="1200"
189 height="600"
190 type="image/webp"
191 />
192 <img
193 src="/hero-desktop.jpg"
194 width="1200"
195 height="600"
196 fetchpriority="high"
197 alt="Hero image description"
198 />
199</picture>
200 
201<!-- GOOD: Below-the-fold image — lazy loaded + async decoding -->
202<img
203 src="/content.webp"
204 width="800"
205 height="400"
206 loading="lazy"
207 decoding="async"
208 alt="Content image description"
209/>
210```
211 
212#### Unnecessary Re-renders (React)
213 
214```tsx
215// BAD: Creates new object on every render, causing children to re-render
216function TaskList() {
217 return <TaskFilters options={{ sortBy: 'date', order: 'desc' }} />;
218}
219 
220// GOOD: Stable reference
221const DEFAULT_OPTIONS = { sortBy: 'date', order: 'desc' } as const;
222function TaskList() {
223 return <TaskFilters options={DEFAULT_OPTIONS} />;
224}
225 
226// Use React.memo for expensive components
227const TaskItem = React.memo(function TaskItem({ task }: Props) {
228 return <div>{/* expensive render */}</div>;
229});
230 
231// Use useMemo for expensive computations
232function TaskStats({ tasks }: Props) {
233 const stats = useMemo(() => calculateStats(tasks), [tasks]);
234 return <div>{stats.completed} / {stats.total}</div>;
235}
236```
237 
238#### Large Bundle Size
239 
240```typescript
241// Modern bundlers (Vite, webpack 5+) handle named imports with tree-shaking automatically,
242// provided the dependency ships ESM and is marked `sideEffects: false` in package.json.
243// Profile before changing import styles — the real gains come from splitting and lazy loading.
244 
245// GOOD: Dynamic import for heavy, rarely-used features
246const ChartLibrary = lazy(() => import('./ChartLibrary'));
247 
248// GOOD: Route-level code splitting wrapped in Suspense
249const SettingsPage = lazy(() => import('./pages/Settings'));
250 
251function App() {
252 return (
253 <Suspense fallback={<Spinner />}>
254 <SettingsPage />
255 </Suspense>
256 );
257}
258```
259 
260#### Missing Caching (Backend)
261 
262```typescript
263// Cache frequently-read, rarely-changed data
264const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
265let cachedConfig: AppConfig | null = null;
266let cacheExpiry = 0;
267 
268async function getAppConfig(): Promise<AppConfig> {
269 if (cachedConfig && Date.now() < cacheExpiry) {
270 return cachedConfig;
271 }
272 cachedConfig = await db.config.findFirst();
273 cacheExpiry = Date.now() + CACHE_TTL;
274 return cachedConfig;
275}
276 
277// HTTP caching headers for static assets
278app.use('/static', express.static('public', {
279 maxAge: '1y', // Cache for 1 year
280 immutable: true, // Never revalidate (use content hashing in filenames)
281}));
282 
283// Cache-Control for API responses
284res.set('Cache-Control', 'public, max-age=300'); // 5 minutes
285```
286 
287### Step 4: Verify (Keep or Revert)
288 
289A fix is a hypothesis until you re-measure. This step decides whether it survives.
290 
291**Re-measure the way you measured the baseline:** same command, same conditions, same fixed budget (wall-clock, sample count, or request count). A baseline taken on a cold cache against a result taken on a warm one measures the cache, not your change.
292 
293**Change one thing at a time.** Three optimizations landed together produce one number, and you cannot attribute it. If they must ship together, measure each in isolation first.
294 
295**Beat the noise, not just the mean.** Repeat the measurement and compare the delta against run-to-run variance. A 3% gain inside ±5% variance is not a gain; it is a different sample.
296 
297Then decide, strictly:
298 
299| Result vs. baseline | Action |
300|---|---|
301| Past the threshold, tests green | **Keep.** Commit with the before/after numbers in the message. |
302| Within noise (no measurable change) | **Revert.** |
303| Worse | **Revert.** |
304| Improved, but a test went red | **Revert.** A regression wearing a win's clothing. |
305 
306**"Neutral" is a revert, not a keep.** This is the step teams skip: the change is already written, throwing it away feels wasteful, so it lands unmeasured, and the codebase accretes complexity that never bought anything. Code you keep, you maintain forever. Make it pay for itself.
307 
308**Correctness gates the metric.** The suite stays green *and* the number moves. An "optimization" that wins by dropping work the product needed (skipping a validation, caching something that must be fresh, removing an `await` that was load-bearing) is a regression, not a win.
309 
310#### Log every attempt, including the reverted ones
311 
312Reverted work leaves no trace in git history, which is exactly why the same dead idea gets tried again next quarter. Keep a short ledger so a discarded idea stays discarded:
313 
314| Idea | Baseline → Result | Verdict | Why |
315|---|---|---|---|
316| Memoize the row component | INP 240ms → 235ms | reverted | Inside noise (±15ms). Rows weren't the bottleneck. |
317| Virtualize the list | INP 240ms → 90ms | kept | Long tasks gone from the trace. |
318| Preconnect to the API origin | LCP 2.8s → 2.8s | reverted | Already same-origin. |
319 
320A section in the PR description or a `PERF.md` in the repo both work. What matters is that the next person (or the next agent) reads it before proposing an experiment, and doesn't re-run one that already failed.
321 
322## Performance Budget
323 
324Set budgets and enforce them:
325 
326```
327JavaScript bundle: < 200KB gzipped (initial load)
328CSS: < 50KB gzipped
329Images: < 200KB per image (above the fold)
330Fonts: < 100KB total
331API response time: < 200ms (p95)
332Time to Interactive: < 3.5s on 4G
333Lighthouse Performance score: ≥ 90
334```
335 
336**Enforce in CI:**
337```bash
338# Bundle size check
339npx bundlesize --config bundlesize.config.json
340 
341# Lighthouse CI
342npx lhci autorun
343```
344 
345## See Also
346 
347For detailed performance checklists, optimization commands, and anti-pattern reference, see `references/performance-checklist.md`.
348 
349 
350## Common Rationalizations
351 
352| Rationalization | Reality |
353|---|---|
354| "We'll optimize later" | Performance debt compounds. Fix obvious anti-patterns now, defer micro-optimizations. |
355| "It's fast on my machine" | Your machine isn't the user's. Profile on representative hardware and networks. |
356| "This optimization is obvious" | If you didn't measure, you don't know. Profile first. |
357| "Users won't notice 100ms" | Research shows 100ms delays impact conversion rates. Users notice more than you think. |
358| "The framework handles performance" | Frameworks prevent some issues but can't fix N+1 queries or oversized bundles. |
359| "It didn't help much, but it doesn't hurt" | Neutral changes are a revert. You pay maintenance on them forever and got nothing back. |
360| "We already wrote it, may as well keep it" | Sunk cost. The measurement doesn't care how long the change took to write. |
361| "The improvement is obvious, no need to re-measure" | Then re-measuring is cheap and proves it. Unmeasured wins are how neutral complexity lands. |
362 
363## Red Flags
364 
365- Optimization without profiling data to justify it
366- N+1 query patterns in data fetching
367- List endpoints without pagination
368- Images without dimensions, lazy loading, or responsive sizes
369- Bundle size growing without review
370- No performance monitoring in production
371- `React.memo` and `useMemo` everywhere (overusing is as bad as underusing)
372- Optimizations kept without a re-measurement that justifies them
373- Several optimizations bundled into one measurement, so no single change can be attributed
374- A "win" that required a test to be changed, skipped, or deleted
375- The same failed optimization attempted more than once because nobody recorded the first attempt
376 
377## Verification
378 
379After any performance-related change:
380 
381- [ ] Before and after measurements exist (specific numbers)
382- [ ] The result was re-measured the same way as the baseline (same command, same conditions)
383- [ ] The improvement exceeds run-to-run variance, not just the mean
384- [ ] Changes that didn't beat the baseline were reverted, not kept as neutral
385- [ ] Attempts are logged, kept and reverted alike, so a dead idea isn't re-run
386- [ ] The specific bottleneck is identified and addressed
387- [ ] Core Web Vitals are within "Good" thresholds
388- [ ] Bundle size hasn't increased significantly
389- [ ] No N+1 queries in new data fetching code
390- [ ] Performance budget passes in CI (if configured)
391- [ ] Existing tests still pass (optimization didn't break behavior)

Security

Review

  • Gen Agent Trust Hubpass
  • Socketpass
  • Snykpass
  • Runlayerwarn
  • ZeroLeakspass

Preview

addyosmani/agent-skillsaddyosmani/agent-skills

$ npx -y skills add addyosmani/agent-skills --skill performance-optimization

▸ installing to .claude/skills…

✓ performance-optimization ready

Repoaddyosmani/agent-skills
TypeSkills
CategoryBackend & APIs
ForDeveloperArchitect
UpdatedJul 2026
License—
First seenJul 26, 2026

Tags

Skill

Related

6 picks
Type
  1. microsoft avatarazure-messagingTroubleshoot and resolve issues with Azure Messaging SDKs for Event Hubs and Service Bus.SkillsJul 2026473k1.3k
  2. larksuite avatarlark-openapi-explorer飞书/Lark 原生 OpenAPI 探索:从官方文档库中挖掘未经 CLI 封装的原生 OpenAPI 接口。当用户的需求无法被现有 lark-* skill 或 lark-cli 已注册命令满足,需要查找并调用原生飞书 OpenAPI 时使用。SkillsJul 2026386k16k
  3. larksuite avatarlark-skill-maker创建 lark-cli 的自定义 Skill。当用户需要把飞书 API 操作封装成可复用的 Skill(包装原子 API 或编排多步流程)时使用。SkillsJul 2026385k16k
  4. mattpocock avatarimplementImplement a piece of work based on a spec or set of tickets.SkillsJul 2026237k189k
  5. supabase avatarsupabaseUse when doing ANY task involving Supabase. Triggers: Supabase products (Database, Auth, Edge Functions, Realtime, Storage, Vectors, Cron, Queues); client…SkillsJul 2026188k2.4k
  6. firebase avatarfirebase-basicsProvides foundational setup, authentication, and project management workflows for Firebase using the Firebase CLI.SkillsJul 2026117k389