Claude
Skills
Sign in
Back

Performance Optimizer

Included with Lifetime
$97 forever

Optimize application performance and scalability. Use when investigating slow applications, scaling bottlenecks, or improving response times. Covers profiling, caching, database optimization, and frontend performance.

Web Dev

What this skill does


# Performance Optimizer

Make applications fast, scalable, and cost-efficient.

## Core Principle

**Measure first, optimize second.** Don't guess at bottlenecks—profile, measure, then fix the slowest parts.

## Performance Budget

### Web Vitals (Target Metrics)

```yaml
Core Web Vitals:
  Largest Contentful Paint (LCP): < 2.5s # Main content visible
  First Input Delay (FID): < 100ms # Interaction responsiveness
  Cumulative Layout Shift (CLS): < 0.1 # Visual stability

Additional Metrics:
  First Contentful Paint (FCP): < 1.8s # First content rendered
  Time to Interactive (TTI): < 3.8s # Fully interactive
  Total Blocking Time (TBT): < 200ms # Main thread blocked
  Speed Index: < 3.4s # Visual progress

Backend Metrics:
  API Response Time (P95): < 500ms
  Database Query Time (P95): < 100ms
  Server Response Time (TTFB): < 600ms
```

---

## Phase 1: Profiling & Measurement

**Goal**: Identify actual bottlenecks, not perceived ones

### Frontend Profiling

**Chrome DevTools**:

```javascript
// 1. Performance tab → Record → Reload page
// 2. Analyze:
//    - Main thread activity
//    - Network waterfall
//    - JavaScript execution time
//    - Rendering time

// 3. Lighthouse audit
// Run: chrome://lighthouse or `npm i -g lighthouse`
lighthouse https://yoursite.com --view
```

**React DevTools Profiler**:

```javascript
// Wrap component to profile
import { Profiler } from 'react'

function onRenderCallback(id, phase, actualDuration) {
  console.log(`${id} (${phase}) took ${actualDuration}ms`)
}

;<Profiler id="ExpensiveComponent" onRender={onRenderCallback}>
  <ExpensiveComponent />
</Profiler>
```

### Backend Profiling

**Node.js Profiling**:

```bash
# Generate CPU profile
node --prof app.js

# Process profile
node --prof-process isolate-0x*.log > processed.txt

# Flame graphs (better visualization)
npm i -g 0x
0x app.js
```

**Python Profiling**:

```python
import cProfile
import pstats

# Profile function
cProfile.run('slow_function()', 'output.prof')

# Analyze
p = pstats.Stats('output.prof')
p.sort_stats('cumulative').print_stats(20)
```

### Database Profiling

**PostgreSQL**:

```sql
-- Enable query logging
ALTER DATABASE yourdb SET log_min_duration_statement = 100; -- Log queries >100ms

-- Analyze query
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM users WHERE email = '[email protected]';

-- Find slow queries
SELECT query, mean_exec_time, calls
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 20;
```

**MongoDB**:

```javascript
// Enable profiling
db.setProfilingLevel(1, { slowms: 100 })

// View slow queries
db.system.profile.find({ millis: { $gt: 100 } }).sort({ ts: -1 })

// Explain query
db.collection.find({ email: '[email protected]' }).explain('executionStats')
```

---

## Phase 2: Database Optimization

### Add Strategic Indexes

```sql
-- Before: Table scan (slow)
SELECT * FROM users WHERE email = '[email protected]';
-- Execution time: 2000ms on 1M rows

-- After: Index scan (fast)
CREATE INDEX idx_users_email ON users(email);
SELECT * FROM users WHERE email = '[email protected]';
-- Execution time: 5ms

-- Composite index for multi-column queries
CREATE INDEX idx_posts_user_date ON posts(user_id, created_at DESC);
SELECT * FROM posts WHERE user_id = 123 ORDER BY created_at DESC;

-- Partial index for filtered queries
CREATE INDEX idx_active_users ON users(created_at) WHERE is_active = true;
```

### Eliminate N+1 Queries

```typescript
// ❌ Bad: N+1 query problem (101 database queries)
const users = await User.findAll() // 1 query
for (const user of users) {
  user.posts = await Post.findAll({ where: { userId: user.id } }) // N queries
}

// ✅ Good: Eager loading (2 queries)
const users = await User.findAll({
  include: [{ model: Post }]
})

// ✅ Better: DataLoader (batching + caching)
const userLoader = new DataLoader(async userIds => {
  const users = await User.findAll({ where: { id: userIds } })
  return userIds.map(id => users.find(u => u.id === id))
})
```

### Query Optimization

```sql
-- Avoid SELECT *
-- ❌ Bad
SELECT * FROM users WHERE id = 1;

-- ✅ Good
SELECT id, name, email FROM users WHERE id = 1;

-- Use LIMIT
-- ❌ Bad
SELECT * FROM posts ORDER BY created_at DESC;

-- ✅ Good
SELECT * FROM posts ORDER BY created_at DESC LIMIT 20;

-- Avoid functions in WHERE clause
-- ❌ Bad (can't use index)
SELECT * FROM users WHERE LOWER(email) = '[email protected]';

-- ✅ Good (can use index)
SELECT * FROM users WHERE email = '[email protected]';
-- Store email as lowercase, or use generated column + index
```

### Connection Pooling

```typescript
// PostgreSQL connection pool
import { Pool } from 'pg'

const pool = new Pool({
  max: 20, // Maximum connections
  min: 5, // Minimum connections
  idleTimeoutMillis: 30000, // Close idle connections after 30s
  connectionTimeoutMillis: 2000 // Error if can't connect in 2s
})

// Always release connections
const client = await pool.connect()
try {
  const result = await client.query('SELECT * FROM users')
  return result.rows
} finally {
  client.release()
}
```

---

## Phase 3: Caching Strategy

### Multi-Layer Caching

```
Browser Cache (HTTP headers)
  ↓
CDN Cache (Cloudflare, CloudFront)
  ↓
Application Cache (Redis, Memcached)
  ↓
Database Query Cache
  ↓
Database
```

### Redis Caching

```typescript
import Redis from 'ioredis'

const redis = new Redis({
  maxRetriesPerRequest: 3,
  enableReadyCheck: true
})

async function getUser(id: string): Promise<User> {
  const cacheKey = `user:${id}`

  // 1. Check cache
  const cached = await redis.get(cacheKey)
  if (cached) {
    return JSON.parse(cached)
  }

  // 2. Cache miss - fetch from database
  const user = await db.users.findById(id)

  // 3. Store in cache (expire in 1 hour)
  await redis.setex(cacheKey, 3600, JSON.stringify(user))

  return user
}

// Cache invalidation
async function updateUser(id: string, data: Partial<User>) {
  await db.users.update(id, data)
  await redis.del(`user:${id}`) // Invalidate cache
}
```

### HTTP Caching Headers

```typescript
// Express middleware
app.use((req, res, next) => {
  // Static assets: cache for 1 year
  if (req.url.match(/\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2)$/)) {
    res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
  }

  // HTML: no cache (always revalidate)
  if (req.url.endsWith('.html') || req.url === '/') {
    res.setHeader('Cache-Control', 'no-cache, must-revalidate')
  }

  // API responses: cache for 5 minutes
  if (req.url.startsWith('/api/')) {
    res.setHeader('Cache-Control', 'public, max-age=300')
    res.setHeader('ETag', generateETag(req.url))
  }

  next()
})
```

### CDN Configuration

```yaml
Static Assets to CDN:
  - Images: /images/**
  - JavaScript: /js/**
  - CSS: /css/**
  - Fonts: /fonts/**

CDN Settings:
  - Cache duration: 1 year (with versioned URLs)
  - Gzip/Brotli compression: enabled
  - Image optimization: WebP conversion
  - Purge on deploy: yes (via API)

Recommended CDNs:
  - Cloudflare (free tier excellent)
  - CloudFront (AWS integration)
  - Fastly (enterprise, very fast)
```

---

## Phase 4: Frontend Optimization

### Code Splitting & Lazy Loading

```typescript
// React lazy loading
import { lazy, Suspense } from 'react'

// ❌ Bad: Load everything upfront
import Dashboard from './Dashboard'
import AdminPanel from './AdminPanel'

// ✅ Good: Lazy load routes
const Dashboard = lazy(() => import('./Dashboard'))
const AdminPanel = lazy(() => import('./AdminPanel'))

function App() {
  return (
    <Suspense fallback={<LoadingSpinner />}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/admin" element={<AdminPanel />} />
      </Routes>
    </Suspense>
  )
}

// Next.js dynamic imports
import dynamic from 'next/dynamic'

const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <LoadingSpinner />,
  ssr: false // Skip SSR for this component
})
```

### Image Optimization

```jsx
// Next.js Image component (automatic optimization

Related in Web Dev