performance
Web performance optimization. Covers frontend, backend, and database optimization. Use for performance reviews. USE WHEN: user mentions "performance", "slow", "optimization", "Core Web Vitals", "LCP", "INP", "CLS", "bundle size", "lazy load", "caching", "N+1 query", "memory leak", asks about "how to speed up", "improve performance", "reduce load time", "database optimization" DO NOT USE FOR: Algorithm complexity - use computer science fundamentals, Code quality/readability - use `clean-code` instead, Security optimization - use security-specific skills
What this skill does
# Performance Optimization
> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `performance` for comprehensive documentation.
## When NOT to Use This Skill
This skill focuses on runtime performance optimization. Do NOT use for:
- **Algorithm optimization** - Use computer science/data structures fundamentals
- **Code readability** - Use `clean-code` skill (don't sacrifice readability for micro-optimizations)
- **Build time optimization** - Use build tool specific skills (Vite, Webpack, etc.)
- **Developer experience** - Use DX-focused skills and tooling
- **Security hardening** - Use security-specific skills (performance != security)
## Anti-Patterns
| Anti-Pattern | Why It's Bad | Performance Solution |
|--------------|--------------|---------------------|
| **Premature Optimization** | Waste time on non-bottlenecks | Measure first, optimize bottlenecks only |
| **SELECT *** | Fetches unnecessary data | Select only needed columns |
| **N+1 Queries** | Multiple DB roundtrips | Use joins or eager loading |
| **No Caching** | Repeated expensive computations | Cache at appropriate layer (memory, Redis, CDN) |
| **Blocking Operations** | Holds up main thread | Use async/background jobs |
| **Large Bundle** | Slow initial load | Code splitting, lazy loading |
| **No Image Optimization** | Huge assets over network | Compress, modern formats (WebP, AVIF), lazy load |
| **Missing Indexes** | Full table scans | Add indexes on queried columns |
| **Memory Leaks** | Unbounded growth | Clean up listeners, close connections, clear refs |
| **Synchronous I/O** | Blocks event loop | Use async I/O operations |
## Quick Troubleshooting
| Issue | Diagnostic | Solution |
|-------|------------|----------|
| **Slow page load** | Check Network tab | Optimize images, enable compression, use CDN |
| **Poor LCP** | Lighthouse audit | Preload critical resources, optimize largest element |
| **High INP** | Performance profiler | Debounce handlers, use web workers, reduce JS |
| **Layout shifts (CLS)** | Layout Shift Regions | Set dimensions on images/embeds, avoid dynamic content |
| **Slow API response** | APM tools, logging | Add database indexes, cache responses, optimize queries |
| **High memory usage** | Memory profiler | Fix leaks, clear intervals/listeners, use weak refs |
| **Large bundle** | Bundle analyzer | Code split, tree shake, lazy load routes |
| **Slow database query** | EXPLAIN ANALYZE | Add indexes, rewrite query, partition table |
## Frontend Performance
### Core Web Vitals
| Metric | Target | Measurement |
|--------|--------|-------------|
| LCP (Largest Contentful Paint) | < 2.5s | Largest visible element |
| INP (Interaction to Next Paint) | < 200ms | Input responsiveness |
| CLS (Cumulative Layout Shift) | < 0.1 | Visual stability |
### Optimization Techniques
```tsx
// Code splitting
const Dashboard = lazy(() => import('./Dashboard'));
// Image optimization
<Image
src="/hero.jpg"
width={1200}
height={600}
priority // Above fold
placeholder="blur"
/>
// Memoization
const MemoizedComponent = memo(ExpensiveComponent);
const memoizedValue = useMemo(() => computeExpensive(a, b), [a, b]);
const memoizedFn = useCallback(() => handleClick(id), [id]);
// Virtual lists for long lists
<VirtualList items={items} itemHeight={50} />
```
## Backend Performance
```typescript
// N+1 prevention
const usersWithPosts = await prisma.user.findMany({
include: { posts: true } // Single query with join
});
// Caching
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));
// Connection pooling
const pool = new Pool({ max: 20 });
// Async processing
await queue.add('sendEmail', { userId });
```
## Database Performance
```sql
-- Use EXPLAIN ANALYZE
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'x';
-- Add indexes for frequently queried columns
CREATE INDEX idx_users_email ON users(email);
-- Partial indexes
CREATE INDEX idx_active_users ON users(email) WHERE is_active = true;
-- Avoid SELECT *
SELECT id, name, email FROM users;
-- Pagination
SELECT * FROM users ORDER BY id LIMIT 20 OFFSET 0;
```
## Checklist
| Area | Check |
|------|-------|
| Images | Optimized, lazy loaded, proper format |
| JS Bundle | Code split, tree shaken, minified |
| CSS | Critical CSS inline, unused removed |
| Fonts | Preloaded, subset, font-display |
| Caching | CDN, browser cache, API cache |
| Database | Indexes, query optimization |
## Production Readiness
### Monitoring Setup
```typescript
// Web Vitals reporting
import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals';
function sendToAnalytics(metric: Metric) {
const body = JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
page: window.location.pathname,
});
// Use sendBeacon for reliability
navigator.sendBeacon('/analytics', body);
}
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onLCP(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);
```
### Performance Budget
```javascript
// webpack.config.js or vite.config.ts
{
performance: {
maxAssetSize: 250000, // 250KB
maxEntrypointSize: 500000, // 500KB
hints: 'error',
},
}
// Lighthouse CI budget
// lighthouserc.js
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000/'],
},
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.9 }],
'first-contentful-paint': ['error', { maxNumericValue: 2000 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'total-blocking-time': ['error', { maxNumericValue: 300 }],
},
},
},
};
```
### Backend Optimization
```typescript
// Response compression
import compression from 'compression';
app.use(compression({ threshold: 1024 }));
// Response caching headers
function setCacheHeaders(res: Response, maxAge: number) {
res.setHeader('Cache-Control', `public, max-age=${maxAge}, stale-while-revalidate=${maxAge * 2}`);
res.setHeader('Vary', 'Accept-Encoding');
}
// Streaming responses
async function streamLargeData(res: Response) {
const stream = db.users.findMany().cursor();
res.setHeader('Content-Type', 'application/json');
res.write('[');
let first = true;
for await (const user of stream) {
if (!first) res.write(',');
res.write(JSON.stringify(user));
first = false;
}
res.write(']');
res.end();
}
// Query optimization
const users = await prisma.user.findMany({
select: { id: true, name: true, email: true }, // Only needed fields
where: { isActive: true },
take: 20,
orderBy: { createdAt: 'desc' },
});
```
### Database Optimization
```sql
-- Composite indexes for common queries
CREATE INDEX idx_users_active_created
ON users(is_active, created_at DESC)
WHERE is_active = true;
-- Query analysis
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT * FROM users WHERE email = '[email protected]';
-- Connection pooling configuration
-- pgbouncer.ini
[pgbouncer]
pool_mode = transaction
default_pool_size = 20
max_client_conn = 100
```
### CI Performance Testing
```yaml
# .github/workflows/performance.yml
name: Performance
on:
pull_request:
branches: [main]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v10
with:
configPath: ./lighthouserc.js
uploadArtifacts: true
bundle-size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Check bundle size
uses: siddharthkp/bundlesize@v2
with:
files: 'dist/*.js'
maxSize: '250KB'
```
### Caching Strategy
```typescript
// Cache lRelated in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.