# Performance Optimization

> Measure-first performance review of a code change. Use the moment a slice''s diff touches data fetching, rendering, bundle size, or any hot path, or when Core Web Vitals / load-time budgets are in play. Do NOT eyeball performance: profile the running app, cite before/after numbers, and flag N+1 queries, unbounded fetches, oversized bundles, and needless re-renders before the PR opens.

- **Type:** Skill
- **Install:** `agentstack add skill-celestialdust-achilles-skills-performance-optimization`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [celestialdust](https://agentstack.voostack.com/s/celestialdust)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [celestialdust](https://github.com/celestialdust)
- **Source:** https://github.com/celestialdust/achilles-skills/tree/main/skills/performance-optimization

## Install

```sh
agentstack add skill-celestialdust-achilles-skills-performance-optimization
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Performance Optimization

## Purpose

**Stage: Review (fan-out lens — the measure-first performance axis).** This skill is one of the four Review lenses (`code-review` · `code-simplification` · `security-and-hardening` · `performance-optimization`) the orchestrator dispatches as fresh, code-cold subagents in parallel on independent axes. Its job here is not to apply fixes but to *judge a diff on evidence*: profile, then report findings.

Measure 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.

## When to use / when to skip

- Performance requirements exist in the spec (load time budgets, response time SLAs)
- Users or monitoring report slow behavior
- Core Web Vitals scores are below thresholds
- You suspect a change introduced a regression
- Building features that handle large datasets or high traffic

**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.

## Inputs

Refuse to run without both of these — measure-first is the whole point; a review with nothing to measure is theater:

- **The slice diff** (required) — the change under review. No diff → nothing to review; stop and ask the orchestrator for the slice's diff.
- **A way to measure** (required) — the running app, a build, or profiling access (Chrome DevTools / Lighthouse / bundle-analyzer / DB query log). No way to obtain before/after numbers → stop; report `block` with reason "unmeasurable", do not eyeball-bless.

Optional, read if present:
- `acceptance.md` performance budgets (feature-namespaced ids, e.g. `PWR-A*`) — the contractual thresholds this diff must hold.
- `environment.md` — which services / runtimes to profile against (kind enum: service · runtime-dep · mcp).

You are a **fresh, code-cold subagent**: you did not write this diff and you have no test-write access. Judge on evidence only.

## Core Web Vitals Targets

| Metric | Good | Needs Improvement | Poor |
|--------|------|-------------------|------|
| **LCP** (Largest Contentful Paint) | ≤ 2.5s | ≤ 4.0s | > 4.0s |
| **INP** (Interaction to Next Paint) | ≤ 200ms | ≤ 500ms | > 500ms |
| **CLS** (Cumulative Layout Shift) | ≤ 0.1 | ≤ 0.25 | > 0.25 |

## The Optimization Workflow

```
1. MEASURE  → Establish baseline with real data
2. IDENTIFY → Find the actual bottleneck (not assumed)
3. FIX      → Address the specific bottleneck
4. VERIFY   → Measure again, confirm improvement
5. GUARD    → Add monitoring or tests to prevent regression
```

### Step 1: Measure

Two complementary approaches — use both:

- **Synthetic (Lighthouse, DevTools Performance tab):** Controlled conditions, reproducible. Best for CI regression detection and isolating specific issues.
- **RUM (web-vitals library, CrUX):** Real user data in real conditions. Required to validate that a fix actually improved user experience.

**Frontend:**
```bash
# Synthetic: Lighthouse in Chrome DevTools (or CI)
# Chrome DevTools → Performance tab → Record
# Chrome DevTools MCP → Performance trace

# RUM: Web Vitals library in code
import { onLCP, onINP, onCLS } from 'web-vitals';

onLCP(console.log);
onINP(console.log);
onCLS(console.log);
```

**Backend:**
```bash
# Response time logging
# Application Performance Monitoring (APM)
# Database query logging with timing

# Simple timing
console.time('db-query');
const result = await db.query(...);
console.timeEnd('db-query');
```

### Where to Start Measuring

Use the symptom to decide what to measure first:

```
What is slow?
├── First page load
│   ├── Large bundle? --> Measure bundle size, check code splitting
│   ├── Slow server response? --> Measure TTFB in DevTools Network waterfall
│   │   ├── DNS long? --> Add dns-prefetch / preconnect for known origins
│   │   ├── TCP/TLS long? --> Enable HTTP/2, check edge deployment, keep-alive
│   │   └── Waiting (server) long? --> Profile backend, check queries and caching
│   └── Render-blocking resources? --> Check network waterfall for CSS/JS blocking
├── Interaction feels sluggish
│   ├── UI freezes on click? --> Profile main thread, look for long tasks (>50ms)
│   ├── Form input lag? --> Check re-renders, controlled component overhead
│   └── Animation jank? --> Check layout thrashing, forced reflows
├── Page after navigation
│   ├── Data loading? --> Measure API response times, check for waterfalls
│   └── Client rendering? --> Profile component render time, check for N+1 fetches
└── Backend / API
    ├── Single endpoint slow? --> Profile database queries, check indexes
    ├── All endpoints slow? --> Check connection pool, memory, CPU
    └── Intermittent slowness? --> Check for lock contention, GC pauses, external deps
```

### Step 2: Identify the Bottleneck

Common bottlenecks by category:

**Frontend:**

| Symptom | Likely Cause | Investigation |
|---------|-------------|---------------|
| Slow LCP | Large images, render-blocking resources, slow server | Check network waterfall, image sizes |
| High CLS | Images without dimensions, late-loading content, font shifts | Check layout shift attribution |
| Poor INP | Heavy JavaScript on main thread, large DOM updates | Check long tasks in Performance trace |
| Slow initial load | Large bundle, many network requests | Check bundle size, code splitting |

**Backend:**

| Symptom | Likely Cause | Investigation |
|---------|-------------|---------------|
| Slow API responses | N+1 queries, missing indexes, unoptimized queries | Check database query log |
| Memory growth | Leaked references, unbounded caches, large payloads | Heap snapshot analysis |
| CPU spikes | Synchronous heavy computation, regex backtracking | CPU profiling |
| High latency | Missing caching, redundant computation, network hops | Trace requests through the stack |

### Step 3: Fix Common Anti-Patterns

#### N+1 Queries (Backend)

```typescript
// BAD: N+1 — one query per task for the owner
const tasks = await db.tasks.findMany();
for (const task of tasks) {
  task.owner = await db.users.findUnique({ where: { id: task.ownerId } });
}

// GOOD: Single query with join/include
const tasks = await db.tasks.findMany({
  include: { owner: true },
});
```

#### Unbounded Data Fetching

```typescript
// BAD: Fetching all records
const allTasks = await db.tasks.findMany();

// GOOD: Paginated with limits
const tasks = await db.tasks.findMany({
  take: 20,
  skip: (page - 1) * 20,
  orderBy: { createdAt: 'desc' },
});
```

#### Missing Image Optimization (Frontend)

```html

  
  
  
  
  
  
  

```

#### Unnecessary Re-renders (React)

```tsx
// BAD: Creates new object on every render, causing children to re-render
function TaskList() {
  return ;
}

// GOOD: Stable reference
const DEFAULT_OPTIONS = { sortBy: 'date', order: 'desc' } as const;
function TaskList() {
  return ;
}

// Use React.memo for expensive components
const TaskItem = React.memo(function TaskItem({ task }: Props) {
  return {/* expensive render */};
});

// Use useMemo for expensive computations
function TaskStats({ tasks }: Props) {
  const stats = useMemo(() => calculateStats(tasks), [tasks]);
  return {stats.completed} / {stats.total};
}
```

#### Large Bundle Size

```typescript
// Modern bundlers (Vite, webpack 5+) handle named imports with tree-shaking automatically,
// provided the dependency ships ESM and is marked `sideEffects: false` in package.json.
// Profile before changing import styles — the real gains come from splitting and lazy loading.

// GOOD: Dynamic import for heavy, rarely-used features
const ChartLibrary = lazy(() => import('./ChartLibrary'));

// GOOD: Route-level code splitting wrapped in Suspense
const SettingsPage = lazy(() => import('./pages/Settings'));

function App() {
  return (
    }>
      
    
  );
}
```

#### Missing Caching (Backend)

```typescript
// Cache frequently-read, rarely-changed data
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
let cachedConfig: AppConfig | null = null;
let cacheExpiry = 0;

async function getAppConfig(): Promise {
  if (cachedConfig && Date.now() /reviews/-perf.md`. Stable sections the orchestrator's Review gate depends on — change the shape → update the consumer in the same commit:

- `## Verdict` — exactly one token: `pass` | `concerns` | `block`.
  - `block` = a regression past budget or a Core Web Vitals "Poor" band, OR unmeasurable (no profiling access).
  - `concerns` = anti-patterns that degrade at scale (N+1, unbounded query, oversized bundle) but within current budget.
  - `pass` = measured, within budget, no anti-pattern in the changed paths.
- `## Findings` — a list; each item carries: severity (`blocker` | `major` | `minor`), a `file:line` citation into the diff, the **before/after measurement** that justifies it (numbers, not adjectives), and a recommended fix. No finding without a measurement or a named anti-pattern.

Handoff: you do **not** flip `STATE.md` — the orchestrator owns the board. It AND-combines the four Review lenses' verdicts into the slice's review gate; any `block` halts the slice's PR promotion. Your contract ends at the findings file.

## Subagents

For a fresh-context, code-cold pass, dispatch the **`performance-auditor`** agent (`agents/performance-auditor.md`) as an
independent subagent. This skill is the *method*; the agent is the *role* that applies it with no prior
context — preserving maker≠checker. Reach for it when a slice touches a hot path, data fetching, bundle size, or render cost.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [celestialdust](https://github.com/celestialdust)
- **Source:** [celestialdust/achilles-skills](https://github.com/celestialdust/achilles-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-celestialdust-achilles-skills-performance-optimization
- Seller: https://agentstack.voostack.com/s/celestialdust
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
