Development
Best practices for writing performant code across frontend, backend, and database layers.
Copy this complete rule and save it as a .mdc file in your .cursor/rules directory
# Performance Optimization
## Core Web Vitals
### Largest Contentful Paint (LCP) < 2.5s
- Preload critical resources
- Optimize images (WebP, lazy loading)
- Use CDN for static assets
- Minimize render-blocking resources
### First Input Delay (FID) < 100ms
- Break up long tasks
- Use web workers for heavy computation
- Defer non-critical JavaScript
- Optimize event handlers
### Cumulative Layout Shift (CLS) < 0.1
- Set explicit dimensions on images/videos
- Reserve space for dynamic content
- Avoid inserting content above existing content
- Use transform for animations
## Frontend Optimization
### JavaScript
```typescript
// Lazy load components
const HeavyComponent = lazy(() => import('./HeavyComponent'));
// Debounce expensive operations
const debouncedSearch = debounce(search, 300);
// Memoize expensive calculations
const expensiveValue = useMemo(() => computeExpensive(data), [data]);
// Virtualize long lists
<VirtualizedList items={largeArray} rowHeight={50} />
```
### Images
```html
<!-- Responsive images with srcset -->
<img
src="image-800.jpg"
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, 800px"
loading="lazy"
decoding="async"
alt="Description"
/>
<!-- Modern formats with fallback -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description">
</picture>
```
### CSS
```css
/* Use CSS containment */
.card {
contain: layout style paint;
}
/* Prefer transform over position changes */
.animated {
transform: translateX(100px); /* Good */
/* left: 100px; Bad - triggers layout */
}
/* Use will-change sparingly */
.will-animate {
will-change: transform;
}
```
### Bundle Optimization
- Enable tree shaking
- Code split by route
- Analyze bundle with webpack-bundle-analyzer
- Use dynamic imports for large dependencies
- Externalize large libraries to CDN
## Backend Optimization
### Database Queries
```sql
-- Add indexes for frequently queried columns
CREATE INDEX idx_users_email ON users(email);
-- Use EXPLAIN to analyze queries
EXPLAIN ANALYZE SELECT * FROM users WHERE email = '[email protected]';
-- Avoid SELECT * in production
SELECT id, name, email FROM users WHERE active = true;
-- Use pagination for large datasets
SELECT * FROM posts ORDER BY created_at DESC LIMIT 20 OFFSET 40;
```
### N+1 Query Prevention
```typescript
// BAD: N+1 queries
const posts = await db.posts.findMany();
for (const post of posts) {
post.author = await db.users.findUnique({ where: { id: post.authorId } });
}
// GOOD: Single query with join
const posts = await db.posts.findMany({
include: { author: true }
});
```
### Caching Strategies
```typescript
// In-memory cache with TTL
const cache = new Map();
async function getCachedData(key: string, ttl: number = 60000) {
const cached = cache.get(key);
if (cached && Date.now() - cached.timestamp < ttl) {
return cached.data;
}
const data = await fetchData(key);
cache.set(key, { data, timestamp: Date.now() });
return data;
}
// Redis caching pattern
async function getUser(id: string) {
const cached = await redis.get(`user:${id}`);
if (cached) return JSON.parse(cached);
const user = await db.users.findUnique({ where: { id } });
await redis.setex(`user:${id}`, 3600, JSON.stringify(user));
return user;
}
```
## API Optimization
### Response Compression
```typescript
// Enable gzip/brotli compression
app.use(compression());
```
### Pagination
```typescript
// Cursor-based pagination (better for large datasets)
const posts = await db.posts.findMany({
take: 20,
cursor: { id: lastId },
orderBy: { createdAt: 'desc' }
});
```
### Field Selection
```typescript
// Allow clients to request specific fields
// GET /api/users?fields=id,name,email
const fields = req.query.fields?.split(',') || ['*'];
```
## Monitoring & Profiling
### Key Metrics to Track
- Response time (p50, p95, p99)
- Error rate
- Throughput (requests/second)
- CPU and memory usage
- Database query time
### Tools
- **Frontend**: Lighthouse, Web Vitals, Chrome DevTools
- **Backend**: Node.js profiler, APM tools (DataDog, New Relic)
- **Database**: Query analyzers, slow query logs
What this rule helps you achieve