engineering
Performance Optimization Guide
Hands-on procedure for frontend and backend performance tuning — profiling bottlenecks, applying targeted optimizations, and verifying improvements with before/after measurements.
performanceoptimizationprofilingbottlenecklatencyrenderingcaching
Works well with agents
Works well with skills
$ npx skills add The-AI-Directory-Company/(…) --skill performance-optimization-guideperformance-optimization-guide/
SKILL.md
Markdown
| 1 | |
| 2 | # Performance Optimization Guide |
| 3 | |
| 4 | ## Before you start |
| 5 | |
| 6 | Gather the following from the user. If anything is missing, ask before proceeding: |
| 7 | |
| 8 | 1. **What is slow?** — Specific page, endpoint, query, or user action with measured latency |
| 9 | 2. **What is the target?** — Quantified goal (e.g., "LCP under 2s", "API p95 under 200ms") |
| 10 | 3. **What does the profile show?** — Existing flame graphs, traces, or Lighthouse reports (if available) |
| 11 | 4. **What is the stack?** — Frontend framework, backend runtime, database, hosting/CDN |
| 12 | 5. **What has been tried?** — Previous optimization attempts and their measured results |
| 13 | |
| 14 | This skill assumes a performance audit has already identified the bottleneck. If the bottleneck is unknown, run a performance audit first. |
| 15 | |
| 16 | ## Optimization procedure |
| 17 | |
| 18 | ### 1. Reproduce and Baseline |
| 19 | |
| 20 | Before changing anything: |
| 21 | |
| 22 | - Reproduce the slow behavior in a consistent environment (same data, same traffic, same hardware) |
| 23 | - Record the baseline metric with the exact tool you will use to verify the fix |
| 24 | - Run the measurement 3 times minimum — single measurements are unreliable due to variance |
| 25 | - Document: metric name, value, tool, timestamp, conditions |
| 26 | |
| 27 | Never optimize without a reproducible baseline. If you cannot measure it, you cannot verify the fix. |
| 28 | |
| 29 | ### 2. Profile to Find the Root Cause |
| 30 | |
| 31 | Use the appropriate profiler for the layer: |
| 32 | |
| 33 | **Frontend rendering:** |
| 34 | - Chrome DevTools Performance panel — record the slow interaction, look for long tasks (>50ms) |
| 35 | - React Profiler / Vue Devtools — identify components re-rendering unnecessarily |
| 36 | - Lighthouse — automated scoring for LCP, CLS, TBT, TTFB |
| 37 | |
| 38 | **JavaScript bundle:** |
| 39 | - Webpack Bundle Analyzer, `next build --analyze`, or equivalent — find largest modules |
| 40 | - Source map explorer — trace bundle size to specific imports |
| 41 | - Check for duplicate dependencies bundled multiple times |
| 42 | |
| 43 | **Backend latency:** |
| 44 | - APM tool (Datadog, New Relic, OpenTelemetry) — distributed trace of the slow request |
| 45 | - Language profiler (Node.js `--prof`, Python `cProfile`, Go `pprof`) — CPU time per function |
| 46 | - Log timestamps at each stage of the request to find where time accumulates |
| 47 | |
| 48 | **Database queries:** |
| 49 | - `EXPLAIN ANALYZE` on the slow query — check for sequential scans, missing indexes, row estimates |
| 50 | - Query log with execution times — find the top queries by total time (frequency x duration) |
| 51 | - Connection pool metrics — check for exhaustion or excessive wait times |
| 52 | |
| 53 | The profile tells you what to fix. Without it, optimization is guessing. |
| 54 | |
| 55 | ### 3. Apply Targeted Fixes |
| 56 | |
| 57 | Apply one fix at a time. Measure after each. Common optimization patterns by category: |
| 58 | |
| 59 | **Frontend — reduce what ships:** |
| 60 | - Code-split routes with dynamic `import()` — load only the code for the current page |
| 61 | - Tree-shake unused exports — verify with bundle analyzer that dead code is eliminated |
| 62 | - Replace heavy libraries with lighter alternatives (e.g., date-fns instead of moment) |
| 63 | - Lazy-load below-fold images and components with `loading="lazy"` or `Intersection Observer` |
| 64 | |
| 65 | **Frontend — reduce what renders:** |
| 66 | - Memoize expensive computations with `useMemo`/`React.memo` — only where the profiler shows re-render cost |
| 67 | - Virtualize long lists with `react-window` or equivalent — do not render 1000 DOM nodes |
| 68 | - Debounce rapid-fire events (scroll, resize, keystroke search) |
| 69 | - Eliminate layout thrashing — batch DOM reads before DOM writes |
| 70 | |
| 71 | **Backend — reduce work per request:** |
| 72 | - Add caching at the right layer: HTTP cache headers, CDN, application cache (Redis), or query cache |
| 73 | - Parallelize independent operations — `Promise.all` / goroutines / async gather instead of sequential awaits |
| 74 | - Move heavy computation to background jobs — respond immediately, process later |
| 75 | - Paginate large result sets — never return unbounded lists |
| 76 | |
| 77 | **Database — reduce query cost:** |
| 78 | - Add indexes on columns in WHERE, JOIN, ORDER BY — verify with EXPLAIN that the index is used |
| 79 | - Eliminate N+1 queries — batch with `WHERE id IN (...)` or use JOIN/eager loading |
| 80 | - Denormalize read-heavy data — precompute aggregations instead of computing on every request |
| 81 | - Use connection pooling — prevent new connection overhead per query |
| 82 | |
| 83 | ### 4. Verify the Improvement |
| 84 | |
| 85 | After each fix: |
| 86 | |
| 87 | - Run the same measurement from step 1 with identical conditions |
| 88 | - Compare before vs. after — record both values side by side |
| 89 | - Run 3+ measurements to confirm the improvement is consistent, not noise |
| 90 | - Check for regressions in adjacent metrics (e.g., fixing latency but increasing error rate) |
| 91 | |
| 92 | | Fix Applied | Metric | Before | After | Change | |
| 93 | |-------------|--------|--------|-------|--------| |
| 94 | | Code-split dashboard route | JS bundle (dashboard) | 842 KB | 214 KB | -74% | |
| 95 | | Add index on orders.user_id | GET /orders p95 | 1,800ms | 120ms | -93% | |
| 96 | | Redis cache for product list | GET /products p95 | 450ms | 12ms | -97% | |
| 97 | |
| 98 | ### 5. Prevent Regressions |
| 99 | |
| 100 | Optimization without regression prevention is temporary: |
| 101 | |
| 102 | - Add performance budgets to CI (e.g., Lighthouse CI, bundle size checks) |
| 103 | - Set alerting thresholds on the metrics you just improved |
| 104 | - Document what was optimized and why — next developer needs context to avoid reverting it |
| 105 | - Add a performance test for the specific scenario if the toolchain supports it |
| 106 | |
| 107 | ## Quality checklist |
| 108 | |
| 109 | Before delivering optimization results, verify: |
| 110 | |
| 111 | - [ ] Baseline was recorded before any changes, with measurement tool and conditions documented |
| 112 | - [ ] A profiler identified the root cause — optimization was targeted, not speculative |
| 113 | - [ ] Each fix was applied individually and measured separately |
| 114 | - [ ] Before/after comparison uses the same tool, environment, and conditions |
| 115 | - [ ] No regressions introduced in adjacent metrics |
| 116 | - [ ] Regression prevention is in place (CI budget, alert, or test) |
| 117 | |
| 118 | ## Common mistakes |
| 119 | |
| 120 | - **Optimizing without profiling.** Intuition about bottlenecks is wrong more often than right. The profiler shows where time actually goes. |
| 121 | - **Applying multiple fixes at once.** If you change three things and performance improves, you do not know which fix helped. One change, one measurement. |
| 122 | - **Caching without invalidation.** Every cache needs an invalidation strategy. Stale data bugs are harder to diagnose than the original latency. |
| 123 | - **Premature memoization.** `React.memo` and `useMemo` add complexity. Only memoize where the profiler shows expensive re-renders — not everywhere. |
| 124 | - **Optimizing dev mode.** Development builds include extra checks, source maps, and HMR overhead. Always measure production builds. |
| 125 | - **Declaring success without regression prevention.** An optimization without a CI check or alert will be silently undone within weeks. |
| 126 |