- name
- Performance Optimization
- description
- Full-stack performance analysis, optimization patterns, monitoring strategies, React 19 concurrent features, and bundle analysis for 2025+ development
- version
- 1.1.0
- category
- Quality & Optimization
- agents
- ["backend-system-architect","frontend-ui-developer","code-quality-reviewer"]
- keywords
- ["performance","optimization","speed","latency","throughput","caching","profiling","bundle","Core Web Vitals","react-19","virtualization","code-splitting","tree-shaking"]
# Performance Optimization Skill
Comprehensive frameworks for analyzing and optimizing application performance across the entire stack.
## When to Use
- Application feels slow or unresponsive
- Database queries taking too long
- Frontend bundle size too large
- API response times exceed targets
- Core Web Vitals need improvement
- Preparing for scale or high traffic
## Performance Targets
### Core Web Vitals (Frontend)
| Metric | Good | Needs Work |
|--------|------|------------|
| **LCP** (Largest Contentful Paint) | < 2.5s | < 4s |
| **INP** (Interaction to Next Paint) | < 200ms | < 500ms |
| **CLS** (Cumulative Layout Shift) | < 0.1 | < 0.25 |
| **TTFB** (Time to First Byte) | < 200ms | < 600ms |
### Backend Targets
| Operation | Target |
|-----------|--------|
| Simple reads | < 100ms |
| Complex queries | < 500ms |
| Write operations | < 200ms |
| Index lookups | < 10ms |
## Bottleneck Categories
| Category | Symptoms | Tools |
|----------|----------|-------|
| **Network** | High TTFB, slow loading | Network tab, WebPageTest |
| **Database** | Slow queries, pool exhaustion | EXPLAIN ANALYZE, pg_stat_statements |
| **CPU** | High usage, slow compute | Profiler, flame graphs |
| **Memory** | Leaks, GC pauses | Heap snapshots |
| **Rendering** | Layout thrashing | React DevTools, Performance tab |
## Database Optimization
### Key Patterns
1. **Add Missing Indexes** - Turn `Seq Scan` into `Index Scan`
2. **Fix N+1 Queries** - Use JOINs or `include` instead of loops
3. **Cursor Pagination** - Never load all records
4. **Connection Pooling** - Manage connection lifecycle
### Quick Diagnostics
```sql
-- Find slow queries (PostgreSQL)
SELECT query, calls, mean_time / 1000 as mean_seconds
FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;
-- Verify index usage
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;
```
> See `templates/database-optimization.ts` for N+1 fixes and pagination patterns
## Caching Strategy
### Cache Hierarchy
```
L1: In-Memory (LRU, memoization) - fastest
L2: Distributed (Redis/Memcached) - shared
L3: CDN (edge, static assets) - global
L4: Database (materialized views) - fallback
```
### Cache-Aside Pattern
```typescript
const cached = await redis.get(key);
if (cached) return JSON.parse(cached);
const data = await db.query(...);
await redis.setex(key, 3600, JSON.stringify(data));
return data;
```
> See `templates/caching-patterns.ts` for full implementation
## Frontend Optimization
### Bundle Optimization
1. **Code Splitting** - `lazy()` for route-based splitting
2. **Tree Shaking** - Import only what you need
3. **Image Optimization** - WebP/AVIF, lazy loading, proper sizing
### Rendering Optimization
1. **Memoization** - `memo()`, `useCallback()`, `useMemo()`
2. **Virtualization** - Render only visible items in long lists
3. **Batch DOM Operations** - Read all, then write all
> See `templates/frontend-optimization.tsx` for patterns
### Analysis Commands
```bash
# Lighthouse audit
lighthouse http://localhost:3000 --output=json
# Bundle analysis
npx @next/bundle-analyzer # Next.js
npx vite-bundle-visualizer # Vite
```
## API Optimization
### Response Optimization
1. **Field Selection** - Return only requested fields
2. **Compression** - Enable gzip/brotli (threshold: 1KB)
3. **ETags** - Enable 304 responses for unchanged data
4. **Pagination** - Cursor-based for large datasets
> See `templates/api-optimization.ts` for middleware examples
## Monitoring Checklist
### Before Launch
- [ ] Lighthouse score > 90
- [ ] Core Web Vitals pass
- [ ] Bundle size within budget
- [ ] Database queries profiled
- [ ] Compression enabled
- [ ] CDN configured
### Ongoing
- [ ] Performance monitoring active
- [ ] Alerting for degradation
- [ ] Lighthouse CI in pipeline
- [ ] Weekly query analysis
- [ ] Real User Monitoring (RUM)
> See `templates/performance-metrics.ts` for Prometheus metrics setup
---
## Database Query Optimization Deep Dive
### N+1 Query Detection
**Symptoms:**
- One query to get parent records, then N queries for related data
- Rapid sequential database calls in logs
- Linear growth in query count with data size
**Example Problem:**
```python
# ❌ BAD: N+1 query (1 + 8 queries)
analyses = await session.execute(select(Analysis).limit(8)).scalars().all()
for analysis in analyses:
# Each iteration hits DB again!
chunks = await session.execute(
select(Chunk).where(Chunk.analysis_id == analysis.id)
).scalars().all()
```
**Solution:**
```python
# ✅ GOOD: Single query with JOIN (1 query)
from sqlalchemy.orm import selectinload
analyses = await session.execute(
select(Analysis)
.options(selectinload(Analysis.chunks)) # Eager load
.limit(8)
).scalars().all()
# Now analyses[0].chunks is already loaded (no extra query)
```
### Index Selection Strategies
| Index Type | Use Case | Example |
|------------|----------|---------|
| **B-tree** | Equality, range queries | `WHERE created_at > '2025-01-01'` |
| **GIN** | Full-text search, JSONB | `WHERE content_tsvector @@ to_tsquery('python')` |
| **HNSW** | Vector similarity | `ORDER BY embedding <=> '[0.1, 0.2, ...]'` |
| **Hash** | Exact equality only | `WHERE id = 'abc123'` (rare) |
**Index Creation Examples:**
```sql
-- B-tree for timestamp range queries
CREATE INDEX idx_analysis_created ON analyses(created_at DESC);
-- GIN for full-text search (pre-computed tsvector)
CREATE INDEX idx_chunk_tsvector ON chunks USING GIN(content_tsvector);
-- HNSW for vector similarity (pgvector)
CREATE INDEX idx_chunk_embedding ON chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
```
**Real-World Impact:**
- HNSW vs IVFFlat: **17x faster queries** (5ms vs 85ms)
- Pre-computed tsvector: **5-10x faster** than computing on query
### EXPLAIN ANALYZE Deep Dive
```sql
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT c.* FROM chunks c
JOIN analyses a ON c.analysis_id = a.id
WHERE a.status = 'completed'
ORDER BY c.created_at DESC
LIMIT 10;
```
**Key Metrics to Watch:**
- **Seq Scan** → Add index if cost is high
- **Execution Time** → Total query duration
- **Planning Time** → Time spent optimizing query
- **Buffers (shared hit)** → Cache hit ratio (want high)
**Example Output Analysis:**
```
Limit (cost=0.42..1.89 rows=10) (actual time=0.032..0.156 rows=10)
Buffers: shared hit=24
-> Nested Loop (cost=0.42..61.23 rows=415)
-> Index Scan using idx_analysis_status on analyses
Index Cond: (status = 'completed')
Buffers: shared hit=8
-> Index Scan using idx_chunk_analysis on chunks
Index Cond: (analysis_id = a.id)
Buffers: shared hit=16
```
✅ **Good signs**: Index scans, low actual time, high buffer hits
### pg_stat_statements Usage
```sql
-- Enable extension (once)
CREATE EXTENSION pg_stat_statements;
-- Find top 10 slowest queries
SELECT
LEFT(query, 60) AS short_query,
calls,
ROUND(mean_exec_time::numeric, 2) AS avg_ms,
ROUND(total_exec_time::numeric, 2) AS total_ms
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
-- Find queries with low cache hit ratio
SELECT
LEFT(query, 60),
shared_blks_hit,
shared_blks_read,
ROUND(100.0 * shared_blks_hit / NULLIF(shared_blks_hit + shared_blks_read, 0), 2) AS cache_hit_ratio
FROM pg_stat_statements
WHERE shared_blks_read > 0
ORDER BY cache_hit_ratio ASC
LIMIT 10;
```
---
## Advanced Caching Strategies
### Multi-Level Cache Hierarchy
**Production Implementation Example:**
```
L1: Prompt Caching (Claude native) - 90% cost savings, 0ms latency
L2: Redis Semantic Cache - 70-85% cost savings, 5-10ms latency
L3: PostgreSQL Query Cache - materialized views, 50-200ms latency
L4: CDN Edge Cache - static assets, <50ms global latency
```
### Redis Caching Patterns
**1. Cache-Aside (Read-Through)**
```python
async def get_analysis(analysis_id: str) -> Analysis:
# 1. Try cache first
cached = await redis.get(f"analysis:{analysis_id}")
if cached:
return Analysis.parse_raw(cached)
# 2. Cache miss - fetch from DB
analysis = await db.get_analysis(analysis_id)
# 3. Store in cache (5 min TTL)
await redis.setex(
f"analysis:{analysis_id}",
300, # 5 minutes
analysis.json()
)
return analysis
```
**2. Write-Through**
```python
async def update_analysis(analysis: Analysis):
# 1. Write to DB first
await db.update(analysis)
# 2. Update cache immediately
await redis.setex(
f"analysis:{analysis.id}",
300,
analysis.json()
)
```
**3. Semantic Cache (Vector Search)**
```python
async def get_llm_response(query: str) -> str:
# 1. Generate query embedding
query_embedding = await embed_text(query)
# 2. Search for similar cached queries (threshold: 0.92)
cached = await semantic_cache.search(query_embedding, threshold=0.92)
if cached:
return cached.content # 95% cost savings!
# 3. Cache miss - call LLM
response = await llm.complete(query)
# 4. Store in semantic cache
await semantic_cache.store(query_embedding, response)
return response
```
### Cache Invalidation Strategies
| Strategy | Use Case | Example |
|----------|----------|---------|
| **TTL** | Time-based expiry | News feed (5 min) |
| **Write-through** | Immediate consistency | User profile updates |
| **Event-driven** | Publish/subscribe | Invalidate on data change |
| **Versioned keys** | Immutable data | `analysis:{id}:v2` |
**Production Cache Warming Example:**
```python
# Warm cache with popular queries at startup
POPULAR_QUERIES = [
"Latest orders for customer dashboard",
"Top selling products this month",
"Inventory low stock alerts"
]
async def warm_cache():
for query in POPULAR_QUERIES:
# Pre-compute and cache common dashboard queries
await get_dashboard_data(query)
```
### HTTP Caching Headers
```python
from fastapi import Response
@app.get("/api/v1/analyses/{id}")
async def get_analysis(id: str, response: Response):
analysis = await db.get_analysis(id)
# Enable browser caching (5 minutes)
response.headers["Cache-Control"] = "public, max-age=300"
# ETag for conditional requests
etag = hashlib.md5(analysis.json().encode()).hexdigest()
response.headers["ETag"] = f'"{etag}"'
return analysis
```
---
## Profiling Tools & Techniques
### Python Profiling (py-spy)
```bash
# Install py-spy
pip install py-spy
# Profile running FastAPI server (no code changes!)
py-spy record --pid $(pgrep -f uvicorn) --output profile.svg
# Top functions by time
py-spy top --pid $(pgrep -f uvicorn)
# Generate flame graph
py-spy record --pid 12345 --format flamegraph --output flamegraph.svg
```
**Flame Graph Interpretation:**
- **Width** = Time spent in function (wider = slower)
- **Height** = Call stack depth
- **Hot paths** = Look for wide bars at the top
### Frontend Profiling (Chrome DevTools)
**Performance Tab:**
1. Open DevTools → Performance
2. Click Record, interact with app, click Stop
Ver no GitHub