How I use Claude Code for performance optimization — a complete workflow
Performance problems are the worst kind of technical debt. They're invisible until they're critical, hard to reproduce, and even harder to fix without breaking things.
I've spent weeks on performance issues that turned out to be a single N+1 query. Here's the workflow I now use with Claude Code to systematically find and fix performance bottlenecks.
The problem with performance optimization
Most performance work follows a frustrating pattern:
- Something's slow
- You guess at the cause
- You make a change
- You're not sure if it helped
- Repeat
The guessing is the problem. Claude Code lets you replace guessing with systematic profiling and analysis.
My workflow
Step 1: Profile first, optimize second
Before touching any code:
Analyze the performance profile output in perf-report.json.
Identify the top 5 bottlenecks by cumulative time spent.
For each bottleneck, show me:
1. The exact function/query
2. How many times it's called per request
3. The likely root cause
4. Whether it's CPU, memory, or I/O bound
Don't suggest fixes yet — just understand the problem.
This forces analysis before action. Every time I skip this step I regret it.
Step 2: Understand the data access patterns
Most performance problems are database problems in disguise:
Look at all database queries in src/models/ and src/routes/.
For each query:
1. Is it inside a loop? (N+1 problem)
2. Is it missing an index? (check schema.sql)
3. Is it fetching more columns than needed?
4. Could it be cached?
List the worst offenders ranked by estimated query count per request.
I've caught N+1 queries that were firing 200+ times per page load with this prompt.
Step 3: Generate the fixes with benchmarks
Once I know what's broken:
Fix the N+1 query in UserController.getWithPosts().
Requirements:
- Use a JOIN or eager loading instead of lazy loading
- Add the missing index on posts.user_id
- Write a benchmark test that proves the fix is faster
- Don't change the function signature (breaking change)
The benchmark requirement is key — it forces measurable improvement.
Step 4: Memory leak hunting
For memory issues, a different approach:
I'm seeing memory grow from 200MB to 1.2GB over 4 hours.
Here are the heap snapshots: [snapshot1.json] [snapshot2.json]
Compare the two snapshots:
1. What objects are growing?
2. What's holding references to them?
3. Is this a true leak or just unbounded cache growth?
4. Where in the code is the leak most likely happening?
Heap snapshot analysis used to require specialized expertise. Now it's a conversation.
Step 5: Frontend performance
For frontend bottlenecks:
Analyze the webpack bundle stats in stats.json.
Identify:
1. The largest chunks and what's inside them
2. Modules that are duplicated across chunks
3. Which npm packages could be tree-shaken or lazy-loaded
4. Quick wins vs. major refactors
Focus on changes that reduce initial bundle size without breaking code splitting.
Where rate limits actually hit
Performance optimization sessions are brutal on token limits:
- Heap snapshot comparison: Two 50MB JSON files = instant limit
- Flame graph analysis: Deeply nested call trees with thousands of frames
- Full codebase audit: Reading every model and route looking for N+1s
- Bundle analysis: Large webpack stats files
I hit the limit mid-session almost every time. When I do, I use SimplyLouie — it's a $2/month Claude API that doesn't stop mid-analysis.
The math: one performance session finding a query that saves $500/month in database costs vs. paying $20/month for an AI tool. Doesn't compute.
The systematic approach
Performance optimization has a reputation for being an art. It's not — it's a process:
- Measure — don't guess, profile
- Isolate — one variable at a time
- Fix — with the root cause, not the symptom
- Verify — benchmark before and after
- Monitor — set alerts so you catch regressions
Claude Code handles the analysis heavy lifting. You make the judgment calls about which tradeoffs to accept.
What actually worked for me
Recent wins using this workflow:
- Found a cache invalidation bug that was causing 40x the expected database load
- Reduced API response time from 800ms to 90ms by fixing eager loading
- Cut memory usage by 60% by fixing an EventEmitter leak
- Reduced bundle size from 2.4MB to 890KB with proper code splitting
None of these required architectural changes. Just systematic analysis.
Running long profiling sessions? SimplyLouie is $2/month — 10x cheaper than ChatGPT, same Claude model. 7-day free trial.
Top comments (0)