AI can write code. But can it make existing code better?
The answer is complicated. Current tools are great at generating new code and terrible at understanding existing systems. Let me explain what real AI code optimization looks like and why most tools fall short.
The Autocomplete Trap
Most "AI code optimization" is just autocomplete with extra steps:
// You write:
function calc
// AI suggests:
function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
Useful, but this isn't optimization. It's generation.
Real optimization would be:
- Identifying that
calculateTotalis called 47 times in a loop - Recognizing the N+1 query pattern
- Suggesting a batch operation instead
That requires understanding, not pattern completion.
What Real Optimization Looks Like
Performance Optimization
// Original code (works but slow)
async function getUsersWithOrders() {
const users = await db.user.findMany();
return Promise.all(
users.map(async (user) => ({
...user,
orders: await db.order.findMany({
where: { userId: user.id }
})
}))
);
}
Pattern completion AI: "Looks fine, maybe add types."
Understanding-based AI:
Performance Issue Detected:
- N+1 query pattern (100 users = 101 queries)
- Current execution: O(n) database calls
Suggested optimization:
async function getUsersWithOrders() {
return db.user.findMany({
include: { orders: true }
});
}
Impact: Reduces queries from n+1 to 1
Risk: Low (same data returned)
The difference? One understands the code runs; the other just sees text.
Architectural Optimization
// Scattered across codebase
// file1.ts
export function formatDate(date: Date): string {
return date.toISOString().split('T')[0];
}
// file2.ts
export function dateToString(d: Date): string {
return d.toISOString().split('T')[0];
}
// file3.ts
const formatDateStr = (date: Date) => date.toISOString().split('T')[0];
Pattern AI: Doesn't even see this as a problem.
Understanding AI:
Duplication Detected:
- 3 implementations of date formatting
- Identical logic in different locations
Suggested optimization:
- Consolidate to single utility in shared/dateUtils.ts
- Update 3 call sites to use shared implementation
Files affected: file1.ts, file2.ts, file3.ts
Call sites to update: 23
This requires scanning the entire codebase and understanding semantic similarity, not just text matching.
Complexity Optimization
// 200-line function (simplified)
async function processOrder(order: Order) {
// Validation (50 lines)
if (!order.items) throw new Error('...');
// ... more validation
// Payment (60 lines)
const payment = await processPayment(order);
// ... payment logic
// Fulfillment (50 lines)
await reserveInventory(order);
// ... fulfillment logic
// Notification (40 lines)
await sendConfirmation(order);
// ... notification logic
}
Pattern AI: "Function is long. Consider splitting." (Unhelpful)
Understanding AI:
Complexity Analysis:
- Function handles 4 distinct responsibilities
- Cyclomatic complexity: 34
- Each section has independent failure modes
Suggested refactor:
async function processOrder(order: Order) {
validateOrder(order);
const payment = await processPayment(order);
await fulfillOrder(order, payment);
await notifyCustomer(order);
}
Benefits:
- Each function testable independently
- Failure isolation (payment failure doesn't affect inventory)
- Easier to modify one section without touching others
Generated functions:
- validateOrder (lines 1-50)
- processPayment (lines 51-110)
- fulfillOrder (lines 111-160)
- notifyCustomer (lines 161-200)
Why Current Tools Fail
They Don't See the Graph
Optimization requires understanding relationships:
- What calls this function?
- What does this function call?
- How does data flow through the system?
Without a call graph, you're optimizing blind.
They Don't Know the Codebase
Generic suggestions based on the code in front of you miss:
- Existing utilities you should use
- Patterns the team already follows
- Libraries already in the project
// AI suggests
import dayjs from 'dayjs';
// But your codebase already uses
import { DateTime } from 'luxon';
Now you have two date libraries. Thanks, AI.
They Can't Measure Impact
"Optimize this" needs context:
- How often is this code called?
- Is this on a hot path?
- Does optimization here matter?
Optimizing a function called once at startup is worthless. Optimizing a function called 1000x per request is valuable.
What We Built Instead
Our approach to AI optimization starts with understanding:
// Before suggesting anything, we analyze:
const context = {
callers: await findCallers(functionName),
callees: await findCallees(functionName),
frequency: await getCallFrequency(functionName),
dependencies: await getImports(file),
existingUtils: await findSimilarPatterns(codePattern),
teamPatterns: await getProjectConventions(project)
};
Then optimization suggestions come with:
- Impact score - Is this worth doing?
- Risk score - What might break?
- Blast radius - What files need to change?
- Existing alternatives - What already exists in the codebase?
The Optimization That Matters
Here's a framework for thinking about AI code optimization:
| Type | AI Can Do | AI Struggles With | |------|-----------|-------------------| | Syntax | Formatting, linting | - | | Performance | Local patterns (N+1) | System-wide bottlenecks | | Architecture | Suggesting splits | Knowing where splits should go | | Duplication | Finding similar code | Understanding semantic equivalence | | Security | Known vulnerability patterns | Context-specific risks |
The sweet spot is AI that understands context before suggesting changes.
Practical Advice
If you're using AI for code optimization:
- Don't trust blind suggestions - AI doesn't know your architecture
- Always check for existing solutions - New code isn't always better
- Measure before optimizing - Is this code even a bottleneck?
- Context is everything - A suggestion in isolation might break in context
The future isn't AI that writes code for you. It's AI that understands your codebase well enough to suggest improvements that actually make sense.
That requires tools that build real understanding — call graphs, dependency maps, and feature context. Not just pattern matching on the function in front of you.