| name | performance-optimizer |
| description | Profile and optimize application performance across frontend, backend, and database layers. Covers bundle analysis, Core Web Vitals, Lighthouse optimization, lazy loading, code splitting, image optimization, caching strategies, database query optimization, memory leak detection, and server response time reduction. Use when optimizing performance or debugging slowness. |
Performance Optimization
Frontend Performance
Core Web Vitals Targets
| Metric | Good | Needs Work | Poor |
|---|
| LCP (Largest Contentful Paint) | ≤ 2.5s | ≤ 4s | > 4s |
| INP (Interaction to Next Paint) | ≤ 200ms | ≤ 500ms | > 500ms |
| CLS (Cumulative Layout Shift) | ≤ 0.1 | ≤ 0.25 | > 0.25 |
Bundle Optimization
npx -y vite-bundle-visualizer
npx -y @next/bundle-analyzer
npx -y source-map-explorer dist/main.js
Code Splitting
const DashboardPage = lazy(() => import("./pages/Dashboard"));
const HeavyChart = lazy(() => import("./components/HeavyChart"));
function Dashboard() {
return (
<Suspense fallback={<Skeleton className="h-64" />}>
<HeavyChart data={data} />
</Suspense>
);
}
Image Optimization
import Image from "next/image";
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={630}
priority // Above-the-fold images
placeholder="blur" // Smooth loading
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
<picture>
<source srcSet="/hero.avif" type="image/avif" />
<source srcSet="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero" loading="lazy" decoding="async" width="1200" height="630" />
</picture>
Resource Loading
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preconnect" href="https://api.example.com" />
<link rel="dns-prefetch" href="https://cdn.example.com" />
<script src="/analytics.js" defer></script>
CSS Optimization
.below-fold { content-visibility: auto; contain-intrinsic-size: auto 500px; }
.animate { transform: translateX(100px); }
.avoid { left: 100px; }
Backend Performance
Response Time Optimization
const users = await prisma.user.findMany({
select: { id: true, name: true, email: true },
take: 20,
cursor: lastId ? { id: lastId } : undefined,
});
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
Caching Strategies
const cache = new Map<string, { data: unknown; expiry: number }>();
function getCached<T>(key: string): T | null {
const entry = cache.get(key);
if (!entry || Date.now() > entry.expiry) {
cache.delete(key);
return null;
}
return entry.data as T;
}
function setCached(key: string, data: unknown, ttlMs: number = 60000): void {
cache.set(key, { data, expiry: Date.now() + ttlMs });
}
res.set("Cache-Control", "public, max-age=3600, s-maxage=86400, stale-while-revalidate=86400");
res.set("ETag", computeEtag(data));
Async Processing
await emailQueue.add("send-welcome", { userId }, { delay: 0 });
app.get("/api/export", async (req, res) => {
res.setHeader("Content-Type", "application/json");
res.write("[");
const cursor = prisma.user.findMany({ cursor: true });
let first = true;
for await (const chunk of cursor) {
res.write(`${first ? "" : ","}${JSON.stringify(chunk)}`);
first = false;
}
res.end("]");
});
Database Performance
Query Analysis
EXPLAIN ANALYZE SELECT * FROM post WHERE author_id = '123' ORDER BY created_at DESC LIMIT 20;
SELECT * FROM pg_stat_user_tables WHERE seq_scan > idx_scan AND n_live_tup > 10000;
Index Optimization
CREATE INDEX idx_post_author_date ON post(author_id, created_at DESC);
CREATE INDEX idx_active_subscriptions ON subscription(user_id) WHERE status = 'active';
CREATE INDEX idx_post_listing ON post(author_id, created_at DESC) INCLUDE (title, slug);
Memory Leak Detection
Node.js Profiling
setInterval(() => {
const usage = process.memoryUsage();
if (usage.heapUsed > 500 * 1024 * 1024) {
logger.warn("High memory usage", {
heapUsed: `${(usage.heapUsed / 1024 / 1024).toFixed(1)}MB`,
rss: `${(usage.rss / 1024 / 1024).toFixed(1)}MB`,
});
}
}, 30000);
Common Leak Patterns
emitter.on("data", handler);
const handler = (data) => process(data);
emitter.on("data", handler);
onCleanup(() => emitter.off("data", handler));
const cache = {};
cache[key] = data;
import { LRUCache } from "lru-cache";
const cache = new LRUCache({ max: 1000, ttl: 60000 });
Performance Checklist