| name | arch-performance-optimization |
| description | Use when analyzing and improving performance for database queries, API endpoints, or frontend rendering. |
| allowed-tools | Read, Write, Edit, Grep, Glob, Bash, Task |
Performance Optimization Workflow
When to Use This Skill
- Slow API response times
- Database query optimization
- Frontend rendering issues
- Memory usage concerns
- Scalability planning
Pre-Flight Checklist
Performance Analysis Framework
Step 1: Identify Bottleneck Type
Performance Issue
├── Database (slow queries, N+1)
├── API (serialization, processing)
├── Network (payload size, latency)
└── Frontend (rendering, bundle size)
Step 2: Measure Baseline
curl -w "@curl-format.txt" -o /dev/null -s "http://api/endpoint"
SET STATISTICS TIME ON;
SELECT * FROM Table WHERE ...;
npm run build -- --stats-json
npx webpack-bundle-analyzer stats.json
Database Optimization
N+1 Query Detection
var employees = await repo.GetAllAsync();
foreach (var emp in employees)
{
Console.WriteLine(emp.Department.Name);
}
var employees = await repo.GetAllAsync(
e => e.CompanyId == companyId,
ct,
e => e.Department,
e => e.Manager
);
Query Optimization
var employees = await repo.GetAllAsync();
var names = employees.Select(e => e.Name);
var names = await repo.GetAllAsync(
q => q.Where(e => e.IsActive)
.Select(e => e.Name));
Index Recommendations
CREATE INDEX IX_Employee_CompanyId ON Employees(CompanyId);
CREATE INDEX IX_Employee_Status ON Employees(Status);
CREATE INDEX IX_Employee_Company_Status
ON Employees(CompanyId, Status)
INCLUDE (FullName, Email);
CREATE FULLTEXT INDEX ON Employees(FullName, Email);
Paging Patterns
var all = await repo.GetAllAsync();
var page = all.Skip(skip).Take(take);
var page = await repo.GetAllAsync(
(uow, q) => q
.Where(e => e.IsActive)
.OrderBy(e => e.Id)
.Skip(skip)
.Take(take));
API Optimization
Parallel Operations
var users = await userRepo.GetAllAsync();
var companies = await companyRepo.GetAllAsync();
var settings = await settingsRepo.GetAllAsync();
var (users, companies, settings) = await (
userRepo.GetAllAsync(),
companyRepo.GetAllAsync(),
settingsRepo.GetAllAsync()
);
Response Size
return new Result { Employee = employee };
return new Result
{
Id = employee.Id,
Name = employee.FullName,
Status = employee.Status
};
Caching
private static readonly ConcurrentDictionary<string, LookupData> _cache = new();
public async Task<LookupData> GetLookupAsync(string key)
{
if (_cache.TryGetValue(key, out var cached))
return cached;
var data = await LoadFromDbAsync(key);
_cache.TryAdd(key, data);
return data;
}
Frontend Optimization
Bundle Size
import _ from 'lodash';
import { debounce } from 'lodash-es/debounce';
Lazy Loading
const routes: Routes = [
{
path: 'feature',
loadChildren: () => import('./feature/feature.module')
.then(m => m.FeatureModule)
}
];
Change Detection
@Component({
changeDetection: ChangeDetectionStrategy.OnPush
})
trackByItem = this.ngForTrackByItemProp<Item>('id');
@for (item of items; track trackByItem)
Virtual Scrolling
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
<cdk-virtual-scroll-viewport itemSize="50">
@for (item of items; track item.id) {
<div class="item">{{ item.name }}</div>
}
</cdk-virtual-scroll-viewport>
Background Job Optimization
Bounded Parallelism
await items.ParallelAsync(ProcessAsync);
await items.ParallelAsync(ProcessAsync, maxConcurrent: 5);
Batch Processing
foreach (var item in items)
await repo.UpdateAsync(item);
await repo.UpdateManyAsync(items, dismissSendEvent: true);
Performance Monitoring
Logging Slow Operations
var sw = Stopwatch.StartNew();
var result = await ExecuteOperation();
sw.Stop();
if (sw.ElapsedMilliseconds > 1000)
Logger.LogWarning("Slow operation: {Ms}ms", sw.ElapsedMilliseconds);
Database Query Logging
optionsBuilder.LogTo(
Console.WriteLine,
new[] { DbLoggerCategory.Database.Command.Name },
LogLevel.Information);
Performance Checklist
Database
API
Frontend
Background Jobs
Anti-Patterns to AVOID
:x: SELECT * in production
var all = await context.Table.ToListAsync();
:x: Synchronous I/O
var result = asyncOperation.Result;
:x: Unbounded result sets
await repo.GetAllAsync();
:x: Repeated database calls in loops
foreach (var id in ids)
await repo.GetByIdAsync(id);
Verification Checklist