Performance Optimization Patterns
Welcome to the comprehensive performance optimization guide for Claude Code. This section consolidates all performance optimization strategies, from managing Claude Code’s own resources to optimizing the applications you build.
🎯 Quick Navigation
Core Resources
- LLM Performance Optimization Guide - Latest techniques for token usage, latency, cost optimization, and caching (2024)
- Advanced Performance Optimization - Cutting-edge optimization techniques
- Advanced Optimization Techniques - Performance profiling, caching strategies, and enterprise-scale optimization
- Advanced Techniques 2025 - Extended thinking modes, context management, and model selection strategies
- Performance Benchmarks - AI model benchmarks and comparisons (2025)
- Performance Deep Dive - Comprehensive performance guide
- Real-Time Performance Monitoring - Live monitoring strategies
Claude Code Performance
- Context Window Management
- Memory Usage Optimization
- Tool Call Optimization
- Response Time Improvements
- Cost Optimization
Application Performance
- Memory Profiling
- Database Query Optimization
- Frontend Bundle Size
- API Response Times
- Performance Monitoring
- Caching Strategies
📊 Optimization Metrics Dashboard
Track these key metrics for optimal performance:
| Metric | Target | Tool |
|---|---|---|
| Token Usage | < 80% of limit | /usage |
| Response Time | < 3s average | Performance logs |
| Context Size | < 50% of window | /memory |
| Error Rate | < 1% | Error tracking |
Claude Code Performance Optimization
Context Window Management
Understanding Context Windows
Claude Code operates within a context window that includes:
- Your current conversation history
- File contents you’ve read
- Tool outputs and results
- System prompts and instructions
- CLAUDE.md file contents
The /compact Command
The /compact command is Claude Code’s most powerful context management feature:
# Compact the current conversation
/compact
# Why use it:
# - Preserves critical information while removing redundancy
# - Immediately frees up context space
# - Maintains conversation continuity
# - Reduces token usage and costsReal-time Context Visibility
Monitor your context usage in real-time:
# Track token usage
npx cc usage
# View current context size
# (Displayed in Claude Code interface)Context Management Strategies
1. Proactive Compaction
Best practice: Use /compact when:
- Context usage exceeds 60%
- Before starting new complex tasks
- After completing major milestones
- When switching between different parts of a project2. Selective File Reading
// Instead of reading entire large files
// BAD: Reading everything
const entireFile = await readFile('large-config.json');
// GOOD: Read only what you need
const config = await readFile('large-config.json', {
offset: 1000, // Start at line 1000
limit: 100 // Read only 100 lines
});3. Structured Information Retention
## CLAUDE.md Best Practices
Include in CLAUDE.md:
- Project architecture overview
- Key file locations
- Common commands
- Coding standards
- Performance considerations
Exclude from CLAUDE.md:
- Detailed implementation code
- Large configuration examples
- Verbose documentation
- Historical change logsMemory Usage Optimization
Environment Configuration
Configure Claude Code for optimal memory usage:
# Set Node.js memory limit (in devcontainer.json or .env)
export NODE_OPTIONS="--max-old-space-size=4096"
# Configure bash timeouts to prevent hung processes
export BASH_DEFAULT_TIMEOUT_MS=120000 # 2 minutes
export BASH_MAX_TIMEOUT_MS=600000 # 10 minutes
# Maintain consistent working directory
export CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=trueShell Snapshot Management
Claude Code uses in-memory shell snapshots stored in ~/.claude:
# Monitor snapshot size
du -sh ~/.claude
# Clean old snapshots if needed
find ~/.claude -type f -mtime +7 -deleteAuto-Compaction Settings
Claude Code auto-compacts at 80% context usage. Monitor and adjust your workflow:
// Pattern: Break complex tasks into stages
async function complexWorkflow() {
// Stage 1: Analysis
await analyzeCodebase();
// Compact after analysis
console.log("Use /compact to free context");
// Stage 2: Implementation
await implementChanges();
// Compact after major changes
console.log("Use /compact before testing");
// Stage 3: Testing
await runTests();
}Tool Call Optimization
Parallel Tool Execution
Maximize performance with parallel tool calls:
// INEFFICIENT: Sequential calls
const status = await bash('git status');
const diff = await bash('git diff');
const log = await bash('git log -5');
// EFFICIENT: Parallel execution
const [status, diff, log] = await Promise.all([
bash('git status'),
bash('git diff'),
bash('git log -5')
]);Batched Operations
Use multi-edit and batched operations:
// INEFFICIENT: Multiple individual edits
await edit('file.ts', 'old1', 'new1');
await edit('file.ts', 'old2', 'new2');
await edit('file.ts', 'old3', 'new3');
// EFFICIENT: Single multi-edit
await multiEdit('file.ts', [
{ old: 'old1', new: 'new1' },
{ old: 'old2', new: 'new2' },
{ old: 'old3', new: 'new3' }
]);Search Optimization
Choose the right search tool for the task:
// For specific file patterns
const files = await glob('**/*.test.ts');
// For content search in known files
const results = await grep('TODO', { glob: '*.ts' });
// For complex, multi-step searches
const findings = await task({
description: "Find all API endpoints",
prompt: "Search for all REST API endpoint definitions"
});Response Time Improvements
Thinking Mode Optimization
Use appropriate thinking levels for different tasks:
## Thinking Mode Guide
1. **No thinking keyword**: Simple, straightforward tasks
- File reads, basic edits, simple searches
2. **"think"**: Moderate complexity
- Design decisions, algorithm choices
3. **"think hard"**: Complex problems
- Architecture design, performance optimization
4. **"think harder"**: Very complex challenges
- Multi-system integration, complex debugging
5. **"ultrathink"**: Extreme complexity
- Novel algorithm design, critical system decisionsPrompt Optimization
Write efficient prompts:
## INEFFICIENT Prompt
"Can you help me understand the codebase and then maybe implement a new feature for user authentication with JWT tokens and also make sure it's secure and follows best practices?"
## EFFICIENT Prompt
"Implement JWT authentication:
1. Add JWT middleware to Express
2. Create /auth/login endpoint
3. Secure existing /api routes
Use bcrypt for passwords, 1h token expiry"Selective Context Loading
Load only necessary context:
// INEFFICIENT: Loading entire modules
import * as utils from './utils';
// EFFICIENT: Specific imports
import { validateEmail, hashPassword } from './utils';Resource Monitoring
Token Usage Tracking
Monitor and analyze token consumption:
# Check current usage
npx cc usage
# Export usage data for analysis
npx cc usage --export usage-report.jsonPerformance Metrics
Track key performance indicators:
interface PerformanceMetrics {
contextUsage: number; // Percentage of context used
responseTime: number; // Average response time
toolCallCount: number; // Number of tool calls
compactionCount: number; // Times /compact used
sessionDuration: number; // Total session time
}
// Log metrics for optimization
function logMetrics(metrics: PerformanceMetrics) {
console.log('Performance Report:', {
...metrics,
efficiency: metrics.toolCallCount / metrics.sessionDuration
});
}Memory Profiling
Monitor Claude Code memory usage:
# Check Node.js memory usage
ps aux | grep claude-code
# Monitor in real-time
top -p $(pgrep -f claude-code)Cost Optimization
Token-Efficient Patterns
Minimize token usage while maintaining quality:
// 1. Use concise variable names in examples
// BAD:
const userAuthenticationTokenWithRefreshCapability = generateToken();
// GOOD:
const authToken = generateToken();
// 2. Avoid redundant file reads
// BAD:
const file1 = await read('config.json');
// ... later ...
const file2 = await read('config.json'); // Redundant
// GOOD:
const config = await read('config.json');
// Reuse config variable
// 3. Summarize large outputs
// When dealing with large API responses or logs
const summary = await task({
prompt: "Summarize key errors from this log",
content: largeLogFile
});Subscription Optimization
Choose the right usage pattern:
## Usage Patterns
### Burst Usage (Development)
- Compact frequently
- Use specific, focused prompts
- Batch similar tasks together
- Clear context between projects
### Sustained Usage (Production)
- Implement CLAUDE.md for persistent context
- Use /compact strategically
- Monitor usage trends
- Set up usage alertsContext Budget Management
Allocate context budget effectively:
class ContextBudget {
private budget = 100; // Percentage
allocate(task: string): number {
const allocations = {
'file-reading': 10,
'code-generation': 20,
'debugging': 30,
'refactoring': 25,
'documentation': 15
};
return allocations[task] || 20;
}
shouldCompact(): boolean {
return this.budget < 20;
}
}Best Practices
1. Strategic Compaction
Compact at these checkpoints:
- [ ] After completing major features
- [ ] Before starting debugging sessions
- [ ] When switching project contexts
- [ ] Before large file operations
- [ ] At natural task boundaries2. Efficient File Management
// Group related file operations
const projectFiles = await Promise.all([
read('src/index.ts'),
read('src/config.ts'),
read('package.json')
]);
// Use glob for bulk operations
const testFiles = await glob('**/*.test.ts');3. CLAUDE.md Optimization
## CLAUDE.md Template
### Project Overview
[2-3 sentences max]
### Key Locations
- API: `/src/api`
- Tests: `/tests`
- Config: `/config`
### Common Commands
```bash
npm run dev # Start development
npm test # Run tests
npm run build # Build projectPerformance Notes
- Large files:
data/*.json(use pagination) - Slow operations: Database migrations
- Memory intensive: Image processing
### 4. **Session Management**
```typescript
// Plan sessions for optimal performance
interface SessionPlan {
tasks: string[];
compactionPoints: number[];
estimatedTokens: number;
}
function planSession(tasks: string[]): SessionPlan {
const plan = {
tasks,
compactionPoints: [],
estimatedTokens: 0
};
// Add compaction after every 3 major tasks
for (let i = 3; i < tasks.length; i += 3) {
plan.compactionPoints.push(i);
}
return plan;
}
5. Tool Selection Guide
## When to use each tool:
### Read
- Specific file contents
- Configuration files
- Small to medium files
### Glob
- Finding files by pattern
- Exploring project structure
- Bulk file operations
### Grep
- Searching for specific content
- Finding usage patterns
- Quick content checks
### Task
- Complex multi-step searches
- When unsure of file locations
- Exploratory analysis
### Bash
- System commands
- Build/test execution
- Git operationsAdvanced Techniques
Long-Term Context Management Protocol (LTCMP)
Implement systematic context preservation:
interface ContextSnapshot {
timestamp: Date;
keyInsights: string[];
completedTasks: string[];
pendingWork: string[];
contextUsage: number;
}
class LTCMPManager {
async saveSnapshot(): Promise<void> {
const snapshot: ContextSnapshot = {
timestamp: new Date(),
keyInsights: this.extractKeyInsights(),
completedTasks: this.getCompletedTasks(),
pendingWork: this.getPendingWork(),
contextUsage: this.getContextUsage()
};
await write('.claude/snapshots/session-${Date.now()}.json',
JSON.stringify(snapshot, null, 2));
}
async loadPreviousContext(): Promise<ContextSnapshot> {
const snapshots = await glob('.claude/snapshots/*.json');
const latest = snapshots.sort().pop();
return JSON.parse(await read(latest));
}
}Predictive Compaction
Anticipate when compaction will be needed:
class PredictiveCompactor {
private usageHistory: number[] = [];
recordUsage(percentage: number): void {
this.usageHistory.push(percentage);
if (this.usageHistory.length > 10) {
this.usageHistory.shift();
}
}
shouldCompactSoon(): boolean {
if (this.usageHistory.length < 3) return false;
// Calculate usage trend
const trend = this.calculateTrend();
const currentUsage = this.usageHistory[this.usageHistory.length - 1];
// Predict next usage
const predictedUsage = currentUsage + trend;
// Recommend compaction if predicted > 75%
return predictedUsage > 75;
}
private calculateTrend(): number {
// Simple linear trend
const recent = this.usageHistory.slice(-3);
return (recent[2] - recent[0]) / 2;
}
}Application Performance Optimization Workflows
Memory Profiling and Optimization
Workflow Steps
-
Initial Memory Baseline
// Step 1: Capture baseline memory usage console.log('Initial memory:', process.memoryUsage()); // Step 2: Set up periodic memory monitoring setInterval(() => { const usage = process.memoryUsage(); console.log(`Memory: RSS ${usage.rss / 1024 / 1024} MB, Heap ${usage.heapUsed / 1024 / 1024} MB`); }, 5000); -
Connect Chrome DevTools
# Start Node.js with inspector node --inspect server.js # Open chrome://inspect in Chrome browser # Take initial heap snapshot -
Identify Memory Leaks
- Take heap snapshot before operation
- Perform the suspected leaky operation multiple times
- Take heap snapshot after operation
- Compare snapshots to identify growing objects
-
Common Memory Leak Patterns to Check
-
Event Listeners: Check for unremoved listeners
// Bad emitter.on('data', handler); // Good emitter.on('data', handler); // Later... emitter.removeListener('data', handler); -
Closures Holding State: Review nested closures
// Problematic closure pattern function createLeak() { const largeData = new Array(1000000); return function() { // This closure keeps largeData in memory console.log(largeData.length); }; } -
Unbounded Caches: Implement eviction strategies
// Use LRU cache with max size const LRU = require('lru-cache'); const cache = new LRU({ max: 500 });
-
-
Optimization Techniques
- Implement object pooling for frequently created objects
- Use streams for large data processing
- Enable V8 optimizations with proper coding patterns
- Minimize object allocations in hot code paths
-
Verification
- Run stress tests and monitor memory usage
- Ensure garbage collection time remains under 50ms
- Verify memory usage stabilizes over time
Tools to Use
- Chrome DevTools Memory Profiler
- Node.js built-in profiler (
--profflag) - Clinic.js for automated profiling
- Process.memoryUsage() for monitoring
Database Query Optimization
PostgreSQL Optimization Workflow
-
Analyze Current Performance
-- Enable query timing \timing on -- Check slow queries SELECT query, calls, mean_time, total_time FROM pg_stat_statements ORDER BY mean_time DESC LIMIT 10; -
Use EXPLAIN ANALYZE
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE customer_id = 123 AND created_at > '2025-01-01'; -
Index Optimization
-- Check missing indexes SELECT schemaname, tablename, attname, n_distinct, correlation FROM pg_stats WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND n_distinct > 100 AND correlation < 0.1 ORDER BY n_distinct DESC; -- Create appropriate indexes CREATE INDEX CONCURRENTLY idx_orders_customer_created ON orders(customer_id, created_at); -
Query Rewriting
- Replace subqueries with JOINs where appropriate
- Use CTEs for complex queries
- Implement proper pagination with LIMIT/OFFSET
- Consider materialized views for complex aggregations
-
Statistics and Maintenance
-- Update statistics ANALYZE orders; -- Check table bloat SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size FROM pg_tables ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC LIMIT 20; -- Vacuum if needed VACUUM ANALYZE orders;
MySQL Optimization Workflow
-
Enable Slow Query Log
SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 2; -
Analyze Query Performance
EXPLAIN FORMAT=JSON SELECT * FROM products p JOIN categories c ON p.category_id = c.id WHERE p.price > 100; -
Optimize Based on Workload
- OLTP: Smaller buffer pool, optimize for writes
- OLAP: Larger buffer pool, optimize for reads
Frontend Bundle Size Reduction
Modern Build Tool Optimization Workflow
-
Analyze Current Bundle
# For Vite npm run build -- --report # For Webpack npm install --save-dev webpack-bundle-analyzer webpack --profile --json > stats.json webpack-bundle-analyzer stats.json -
Enable Tree Shaking
// vite.config.js export default { build: { rollupOptions: { treeshake: { moduleSideEffects: false, propertyReadSideEffects: false, tryCatchDeoptimization: false } } } } // webpack.config.js module.exports = { mode: 'production', // Enables tree shaking optimization: { usedExports: true, minimize: true, sideEffects: false } }; -
Implement Code Splitting
// Route-based splitting const Dashboard = lazy(() => import('./Dashboard')); const Analytics = lazy(() => import('./Analytics')); // Component-based splitting const HeavyComponent = lazy(() => import(/* webpackChunkName: "heavy" */ './HeavyComponent') ); -
Optimize Dependencies
// Replace heavy libraries with lighter alternatives // Before: lodash (70KB) import { debounce } from 'lodash'; // After: lodash-es with tree shaking (4KB) import debounce from 'lodash-es/debounce'; // Or use native alternatives const debounce = (fn, delay) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn(...args), delay); }; }; -
Vendor Splitting
// vite.config.js build: { rollupOptions: { output: { manualChunks: { vendor: ['react', 'react-dom'], ui: ['@mui/material'], utils: ['lodash-es', 'date-fns'] } } } } -
Monitor Bundle Size
// package.json { "scripts": { "build": "vite build", "analyze": "vite build --report", "size-limit": "size-limit" }, "size-limit": [ { "path": "dist/assets/index-*.js", "limit": "150 KB" } ] }
API Response Time Improvements
Optimization Workflow
-
Implement Request-Level Monitoring
// Express middleware for timing app.use((req, res, next) => { const start = process.hrtime.bigint(); res.on('finish', () => { const duration = Number(process.hrtime.bigint() - start) / 1000000; console.log(`${req.method} ${req.path} - ${duration}ms`); }); next(); }); -
Database Query Optimization
// Add query timing const { Client } = require('pg'); const client = new Client(); client.query = (function(originalQuery) { return async function(...args) { const start = Date.now(); try { const result = await originalQuery.apply(this, args); const duration = Date.now() - start; if (duration > 100) { console.warn(`Slow query (${duration}ms):`, args[0]); } return result; } catch (error) { throw error; } }; })(client.query.bind(client)); -
Implement Caching Layers
// Memory cache for hot data const NodeCache = require('node-cache'); const cache = new NodeCache({ stdTTL: 600 }); // Redis for distributed cache const redis = require('redis'); const client = redis.createClient(); async function getCachedData(key, fetchFn) { // Check memory cache first let data = cache.get(key); if (data) return data; // Check Redis data = await client.get(key); if (data) { cache.set(key, JSON.parse(data)); return JSON.parse(data); } // Fetch from source data = await fetchFn(); // Store in both caches cache.set(key, data); await client.setex(key, 3600, JSON.stringify(data)); return data; } -
Optimize Payload Size
// Enable compression const compression = require('compression'); app.use(compression()); // Implement field filtering app.get('/api/users', (req, res) => { const fields = req.query.fields?.split(',') || []; const users = getUsers(); if (fields.length > 0) { const filtered = users.map(user => fields.reduce((obj, field) => { obj[field] = user[field]; return obj; }, {}) ); res.json(filtered); } else { res.json(users); } }); -
Implement CDN and Edge Computing
// Configure CDN headers app.use((req, res, next) => { if (req.path.startsWith('/static/')) { res.set('Cache-Control', 'public, max-age=31536000'); } else if (req.path.startsWith('/api/')) { res.set('Cache-Control', 'private, max-age=0'); } next(); }); // Edge function example (Cloudflare Workers) addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { const cache = caches.default; let response = await cache.match(request); if (!response) { response = await fetch(request); if (response.status === 200) { const headers = new Headers(response.headers); headers.set('Cache-Control', 'max-age=300'); response = new Response(response.body, { status: response.status, statusText: response.statusText, headers: headers }); event.waitUntil(cache.put(request, response.clone())); } } return response; }
Automated Performance Regression Detection
CI/CD Integration Workflow
-
Set Up Lighthouse CI
# .github/workflows/lighthouse.yml name: Lighthouse CI on: [push, pull_request] jobs: lighthouse: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 - run: npm ci - run: npm run build - name: Run Lighthouse CI uses: treosh/lighthouse-ci-action@v9 with: configPath: './lighthouserc.json' uploadArtifacts: true temporaryPublicStorage: true -
Configure Performance Budgets
// lighthouserc.json { "ci": { "collect": { "numberOfRuns": 3, "startServerCommand": "npm run serve", "url": ["http://localhost:3000"] }, "assert": { "preset": "lighthouse:recommended", "assertions": { "categories:performance": ["error", {"minScore": 0.9}], "first-contentful-paint": ["error", {"maxNumericValue": 2000}], "largest-contentful-paint": ["error", {"maxNumericValue": 2500}], "total-blocking-time": ["error", {"maxNumericValue": 300}], "cumulative-layout-shift": ["error", {"maxNumericValue": 0.1}], "interactive": ["error", {"maxNumericValue": 3500}] } }, "upload": { "target": "temporary-public-storage" } } } -
Web Vitals Monitoring
// Install: npm install web-vitals import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'; function sendToAnalytics(metric) { // Send to your analytics endpoint fetch('/api/metrics', { method: 'POST', body: JSON.stringify({ name: metric.name, value: metric.value, delta: metric.delta, id: metric.id, url: window.location.href, timestamp: Date.now() }), headers: { 'Content-Type': 'application/json' } }); } getCLS(sendToAnalytics); getFID(sendToAnalytics); getFCP(sendToAnalytics); getLCP(sendToAnalytics); getTTFB(sendToAnalytics); -
Custom Performance Metrics
// Track custom business metrics class PerformanceTracker { constructor() { this.marks = new Map(); } start(name) { this.marks.set(name, performance.now()); } end(name, threshold) { const start = this.marks.get(name); if (!start) return; const duration = performance.now() - start; this.marks.delete(name); // Log if exceeds threshold if (threshold && duration > threshold) { console.warn(`Performance regression: ${name} took ${duration}ms (threshold: ${threshold}ms)`); } // Send to monitoring this.report(name, duration); } report(name, duration) { if ('sendBeacon' in navigator) { navigator.sendBeacon('/api/performance', JSON.stringify({ metric: name, duration, timestamp: Date.now() })); } } } const perf = new PerformanceTracker(); // Usage perf.start('api-call'); const data = await fetchData(); perf.end('api-call', 1000); // Alert if > 1 second
Performance Monitoring Integration
APM Tool Integration Workflow
-
DataDog Integration
// Install: npm install dd-trace const tracer = require('dd-trace').init({ service: 'my-app', env: process.env.NODE_ENV, version: process.env.APP_VERSION, analytics: true, profiling: true, logInjection: true }); // Automatic instrumentation tracer.use('express'); tracer.use('pg'); tracer.use('redis'); // Custom spans app.get('/api/complex-operation', async (req, res) => { const span = tracer.startSpan('complex.operation'); try { span.setTag('user.id', req.user.id); const dbSpan = tracer.startSpan('database.query', { childOf: span }); const data = await db.query('SELECT ...'); dbSpan.finish(); const processSpan = tracer.startSpan('data.processing', { childOf: span }); const result = processData(data); processSpan.finish(); res.json(result); } catch (error) { span.setTag('error', true); span.setTag('error.message', error.message); throw error; } finally { span.finish(); } }); -
New Relic Integration
// newrelic.js exports.config = { app_name: ['My Application'], license_key: process.env.NEW_RELIC_LICENSE_KEY, logging: { level: 'info' }, distributed_tracing: { enabled: true }, transaction_tracer: { enabled: true, transaction_threshold: 'apdex_f', record_sql: 'obfuscated' } }; // app.js require('newrelic'); // Custom instrumentation const newrelic = require('newrelic'); app.get('/api/users/:id', (req, res) => { newrelic.addCustomAttribute('user.id', req.params.id); newrelic.addCustomAttribute('api.version', 'v2'); // Custom metric newrelic.recordMetric('Custom/UserAPI/RequestCount', 1); // Custom event newrelic.recordCustomEvent('UserAPIAccess', { userId: req.params.id, endpoint: req.path, method: req.method }); }); -
Sentry Performance Monitoring
// Install: npm install @sentry/node @sentry/tracing const Sentry = require('@sentry/node'); const { ProfilingIntegration } = require('@sentry/profiling-node'); Sentry.init({ dsn: process.env.SENTRY_DSN, integrations: [ new Sentry.Integrations.Http({ tracing: true }), new Sentry.Integrations.Express({ app }), new ProfilingIntegration() ], tracesSampleRate: 1.0, profilesSampleRate: 1.0 }); // Transaction monitoring app.use(Sentry.Handlers.requestHandler()); app.use(Sentry.Handlers.tracingHandler()); // Custom performance tracking app.post('/api/process', async (req, res) => { const transaction = Sentry.getCurrentHub() .getScope() .getTransaction(); const span = transaction.startChild({ op: 'task', description: 'Process user data' }); try { const result = await processUserData(req.body); span.setStatus('ok'); res.json(result); } catch (error) { span.setStatus('internal_error'); throw error; } finally { span.finish(); } });
Load Testing Automation
k6 Load Testing Workflow
-
Create Test Script
// load-test.js import http from 'k6/http'; import { check, sleep } from 'k6'; import { Rate } from 'k6/metrics'; const errorRate = new Rate('errors'); export const options = { stages: [ { duration: '2m', target: 100 }, // Ramp up { duration: '5m', target: 100 }, // Stay at 100 users { duration: '2m', target: 200 }, // Ramp up to 200 { duration: '5m', target: 200 }, // Stay at 200 { duration: '2m', target: 0 }, // Ramp down ], thresholds: { 'http_req_duration': ['p(95)<500'], // 95% of requests under 500ms 'errors': ['rate<0.1'], // Error rate under 10% }, }; export default function() { const response = http.get('https://api.example.com/users'); const success = check(response, { 'status is 200': (r) => r.status === 200, 'response time < 500ms': (r) => r.timings.duration < 500, }); errorRate.add(!success); sleep(1); } -
CI/CD Integration
# .github/workflows/load-test.yml name: Load Testing on: schedule: - cron: '0 2 * * *' # Daily at 2 AM workflow_dispatch: jobs: k6-load-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run k6 test uses: grafana/k6-action@v0.2.0 with: filename: load-test.js flags: --out json=results.json - name: Upload results uses: actions/upload-artifact@v3 with: name: k6-results path: results.json - name: Check thresholds run: | if grep -q '"passes":false' results.json; then echo "Load test failed thresholds" exit 1 fi
Artillery Load Testing Workflow
-
Create Test Configuration
# load-test.yml config: target: "https://api.example.com" phases: - duration: 60 arrivalRate: 10 name: "Warm up" - duration: 300 arrivalRate: 50 name: "Sustained load" - duration: 60 arrivalRate: 100 name: "Peak load" processor: "./processors.js" payload: path: "./users.csv" fields: - "userId" - "email" scenarios: - name: "User Journey" flow: - post: url: "/auth/login" json: email: "{{ email }}" password: "password123" capture: - json: "$.token" as: "authToken" - get: url: "/users/{{ userId }}" headers: Authorization: "Bearer {{ authToken }}" expect: - statusCode: 200 - contentType: json - hasProperty: "id" - think: 5 - post: url: "/users/{{ userId }}/actions" headers: Authorization: "Bearer {{ authToken }}" json: action: "update_profile" expect: - statusCode: - 200 - 201 -
Run with Performance Thresholds
# Run test with thresholds artillery run load-test.yml --output results.json # Generate report artillery report results.json --output report.html
Caching Strategies Implementation
Redis Caching Implementation Workflow
-
Set Up Caching Infrastructure
// cache.js const Redis = require('ioredis'); const redis = new Redis({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, password: process.env.REDIS_PASSWORD, retryStrategy: (times) => Math.min(times * 50, 2000) }); class CacheManager { constructor(defaultTTL = 3600) { this.defaultTTL = defaultTTL; this.redis = redis; } async get(key) { try { const value = await this.redis.get(key); return value ? JSON.parse(value) : null; } catch (error) { console.error('Cache get error:', error); return null; } } async set(key, value, ttl = this.defaultTTL) { try { await this.redis.setex( key, ttl, JSON.stringify(value) ); } catch (error) { console.error('Cache set error:', error); } } async invalidate(pattern) { const keys = await this.redis.keys(pattern); if (keys.length > 0) { await this.redis.del(...keys); } } // Implement cache-aside pattern async getOrSet(key, fetchFn, ttl = this.defaultTTL) { let value = await this.get(key); if (value === null) { value = await fetchFn(); await this.set(key, value, ttl); } return value; } // Implement write-through pattern async writeThrough(key, value, writeFn, ttl = this.defaultTTL) { await writeFn(value); await this.set(key, value, ttl); return value; } } module.exports = new CacheManager(); -
Implement Distributed Caching for Microservices
// Shared cache strategy const cache = require('./cache'); // Service A app.get('/api/products/:id', async (req, res) => { const key = `product:${req.params.id}`; const product = await cache.getOrSet(key, async () => { return await db.query('SELECT * FROM products WHERE id = ?', [req.params.id]); }, 3600); res.json(product); }); // Service B (can access same cached data) app.get('/api/cart/products/:id', async (req, res) => { const key = `product:${req.params.id}`; const product = await cache.get(key); if (product) { res.json({ cached: true, product }); } else { // Fetch from Service A or database const product = await fetchProduct(req.params.id); res.json({ cached: false, product }); } }); -
Advanced Caching Patterns
// Tag-based cache invalidation class TaggedCache extends CacheManager { async setWithTags(key, value, tags, ttl = this.defaultTTL) { await this.set(key, value, ttl); // Store tags for (const tag of tags) { await this.redis.sadd(`tag:${tag}`, key); await this.redis.expire(`tag:${tag}`, ttl); } } async invalidateByTag(tag) { const keys = await this.redis.smembers(`tag:${tag}`); if (keys.length > 0) { await this.redis.del(...keys); await this.redis.del(`tag:${tag}`); } } } // Usage const taggedCache = new TaggedCache(); // Cache with tags await taggedCache.setWithTags( 'user:123:profile', userData, ['user:123', 'profiles'], 3600 ); // Invalidate all user:123 related cache await taggedCache.invalidateByTag('user:123'); -
Multi-Layer Caching
const NodeCache = require('node-cache'); const memoryCache = new NodeCache({ stdTTL: 60 }); class MultiLayerCache { constructor(redisCache) { this.memory = memoryCache; this.redis = redisCache; } async get(key) { // Check memory cache first let value = this.memory.get(key); if (value !== undefined) { return value; } // Check Redis value = await this.redis.get(key); if (value !== null) { // Store in memory cache this.memory.set(key, value); return value; } return null; } async set(key, value, ttl = 3600) { // Set in both caches this.memory.set(key, value, Math.min(ttl, 300)); // Max 5 min in memory await this.redis.set(key, value, ttl); } } -
Cache Warming and Preloading
// Implement cache warming class CacheWarmer { constructor(cache) { this.cache = cache; this.warmingTasks = new Map(); } register(name, fetchFn, keys, schedule = '0 */6 * * *') { this.warmingTasks.set(name, { fetchFn, keys, schedule }); } async warmCache(name) { const task = this.warmingTasks.get(name); if (!task) return; console.log(`Warming cache for ${name}`); for (const key of task.keys) { try { const value = await task.fetchFn(key); await this.cache.set(key, value); } catch (error) { console.error(`Failed to warm cache for ${key}:`, error); } } } startScheduled() { const cron = require('node-cron'); for (const [name, task] of this.warmingTasks) { cron.schedule(task.schedule, () => { this.warmCache(name); }); } } } // Usage const warmer = new CacheWarmer(cache); warmer.register( 'popular-products', async (id) => await db.getProduct(id), ['prod:1', 'prod:2', 'prod:3'], // Most popular product IDs '0 */4 * * *' // Every 4 hours ); warmer.startScheduled();
Summary
This comprehensive guide provides systematic approaches for optimizing both Claude Code performance and application performance. Key takeaways:
For Claude Code Performance:
- Proactive context management using /compact and monitoring
- Efficient tool usage with parallel execution and batching
- Strategic resource allocation based on task requirements
- Continuous monitoring of usage patterns and costs
- Systematic workflows that incorporate optimization checkpoints
For Application Performance:
- Detection Methods: How to identify performance problems
- Analysis Tools: Specific tools and commands to use
- Implementation Steps: Detailed code examples and configurations
- Verification Procedures: How to confirm improvements
- Monitoring Integration: Ongoing performance tracking
By following these patterns and workflows, developers can maximize Claude Code’s capabilities while maintaining optimal performance and managing costs effectively.
🔗 Related Resources
Documentation
- Memory and Context Optimization Guide - Comprehensive optimization guide
- Subagent Memory Optimization - Advanced subagent patterns
- Context Management Strategies - Deep dive into context window management
- Debugging & Observability - Performance monitoring techniques
Experiments
- Performance Experiments - Cutting-edge performance optimization research
External Resources
Verifications
This document was last verified on 2025-07-21. The information was verified against:
- Claude Code Memory Management: Confirmed from official Anthropic documentation that Claude Code uses CLAUDE.md files for memory management, with project-level and user-level memory support
- /compact Command: Verified from multiple sources including bgadoci.com that /compact is Claude Code’s key context management feature, with automatic compaction now available when approaching context limits
- Context Window Details: Confirmed that Claude Sonnet 4 and Opus 4 both have 200k token context windows, with real-time usage indicators showing percentage of context used
Original sources:
- https://docs.anthropic.com/en/docs/claude-code/memory - Official memory management documentation
- https://bgadoci.com/blog/game-changing-context-management-in-claude-code - Detailed /compact command analysis
- https://www.threads.com/@boris_cherny/post/DHWS7kfyyax/ - Auto-compact feature announcement
- https://www.anthropic.com/engineering/claude-code-best-practices - Official best practices guide