Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:45:50 +08:00
commit bd85f56f7c
78 changed files with 33541 additions and 0 deletions

View File

@@ -0,0 +1,346 @@
---
name: kv-optimization-advisor
description: Automatically optimizes Cloudflare KV storage patterns, suggesting parallel operations, caching strategies, and storage choice guidance
triggers: ["KV operations", "storage access patterns", "sequential storage calls", "large data patterns"]
---
# KV Optimization Advisor SKILL
## Activation Patterns
This SKILL automatically activates when:
- KV `get`, `put`, `delete`, or `list` operations are detected
- Sequential storage operations that could be parallelized
- Large data patterns that might exceed KV limits
- Missing caching opportunities for repeated KV calls
- Storage choice patterns (KV vs R2 vs D1)
## Expertise Provided
### KV Performance Optimization
- **Parallel Operations**: Identifies sequential KV calls that can be parallelized
- **Request-Scoped Caching**: Suggests in-memory caching during request processing
- **Storage Choice Guidance**: Recommends KV vs R2 vs D1 based on use case
- **Value Size Optimization**: Monitors for large values that impact performance
- **Batch Operations**: Suggests batch operations when appropriate
- **TTL Optimization**: Recommends optimal TTL strategies
### Specific Checks Performed
#### ❌ KV Performance Anti-Patterns
```typescript
// These patterns trigger immediate alerts:
// Sequential KV operations (multiple network round-trips)
const user = await env.USERS.get(id); // 10-30ms
const settings = await env.SETTINGS.get(id); // 10-30ms
const prefs = await env.PREFS.get(id); // 10-30ms
// Total: 30-90ms just for storage!
// Repeated KV calls in same request
const user1 = await env.USERS.get(id);
const user2 = await env.USERS.get(id); // Same data fetched twice!
```
#### ✅ KV Performance Best Practices
```typescript
// These patterns are validated as correct:
// Parallel KV operations (single network round-trip)
const [user, settings, prefs] = await Promise.all([
env.USERS.get(id),
env.SETTINGS.get(id),
env.PREFS.get(id),
]);
// Total: 10-30ms (single round-trip)
// Request-scoped caching
const cache = new Map();
async function getCached(key: string, env: Env) {
if (cache.has(key)) return cache.get(key);
const value = await env.USERS.get(key);
cache.set(key, value);
return value;
}
```
## Integration Points
### Complementary to Existing Components
- **edge-performance-oracle agent**: Handles comprehensive performance analysis, SKILL provides immediate KV optimization
- **cloudflare-architecture-strategist agent**: Handles storage architecture decisions, SKILL provides immediate optimization
- **workers-binding-validator SKILL**: Ensures KV bindings are correct, SKILL optimizes usage patterns
### Escalation Triggers
- Complex storage architecture questions → `cloudflare-architecture-strategist` agent
- KV performance troubleshooting → `edge-performance-oracle` agent
- Storage migration strategies → `cloudflare-architecture-strategist` agent
## Validation Rules
### P1 - Critical (Performance Killer)
- **Sequential Operations**: Multiple sequential KV calls that could be parallelized
- **Repeated Calls**: Same KV key fetched multiple times in one request
- **Large Values**: Values approaching 25MB KV limit
### P2 - High (Performance Impact)
- **Missing Caching**: Repeated expensive KV operations without caching
- **Wrong Storage Choice**: Using KV for data that should be in R2 or D1
- **No TTL Strategy**: Missing or inappropriate TTL configuration
### P3 - Medium (Optimization Opportunity)
- **Batch Opportunities**: Multiple operations that could be batched
- **Suboptimal TTL**: TTL values that are too short or too long
- **Missing Error Handling**: KV operations without proper error handling
## Remediation Examples
### Fixing Sequential Operations
```typescript
// ❌ Critical: Sequential KV operations (3x network round-trips)
export default {
async fetch(request: Request, env: Env) {
const userId = getUserId(request);
const user = await env.USERS.get(userId); // 10-30ms
const settings = await env.SETTINGS.get(userId); // 10-30ms
const prefs = await env.PREFS.get(userId); // 10-30ms
// Total: 30-90ms just for storage!
return new Response(JSON.stringify({ user, settings, prefs }));
}
}
// ✅ Correct: Parallel operations (single round-trip)
export default {
async fetch(request: Request, env: Env) {
const userId = getUserId(request);
// Fetch in parallel - single network round-trip time
const [user, settings, prefs] = await Promise.all([
env.USERS.get(userId),
env.SETTINGS.get(userId),
env.PREFS.get(userId),
]);
// Total: 10-30ms (single round-trip)
return new Response(JSON.stringify({ user, settings, prefs }));
}
}
```
### Fixing Repeated Calls with Caching
```typescript
// ❌ High: Same KV data fetched multiple times
export default {
async fetch(request: Request, env: Env) {
const userId = getUserId(request);
// Fetch user data multiple times unnecessarily
const user1 = await env.USERS.get(userId);
const user2 = await env.USERS.get(userId); // Duplicate call!
const user3 = await env.USERS.get(userId); // Duplicate call!
// Process user data...
return new Response('Processed');
}
}
// ✅ Correct: Request-scoped caching
export default {
async fetch(request: Request, env: Env) {
const userId = getUserId(request);
// Request-scoped cache to avoid duplicate KV calls
const cache = new Map();
async function getCachedUser(id: string) {
if (cache.has(id)) return cache.get(id);
const user = await env.USERS.get(id);
cache.set(id, user);
return user;
}
const user1 = await getCachedUser(userId); // KV call
const user2 = await getCachedUser(userId); // From cache
const user3 = await getCachedUser(userId); // From cache
// Process user data...
return new Response('Processed');
}
}
```
### Fixing Storage Choice
```typescript
// ❌ High: Using KV for large files (wrong storage choice)
export default {
async fetch(request: Request, env: Env) {
const fileId = new URL(request.url).searchParams.get('id');
// KV is for small key-value data, not large files!
const fileData = await env.FILES.get(fileId); // Could be 10MB+
return new Response(fileData);
}
}
// ✅ Correct: Use R2 for large files
export default {
async fetch(request: Request, env: Env) {
const fileId = new URL(request.url).searchParams.get('id');
// R2 is designed for large objects/files
const object = await env.FILES_BUCKET.get(fileId);
if (!object) {
return new Response('Not found', { status: 404 });
}
return new Response(object.body);
}
}
```
### Fixing TTL Strategy
```typescript
// ❌ Medium: No TTL strategy (data never expires)
export default {
async fetch(request: Request, env: Env) {
const cacheKey = `data:${Date.now()}`;
// Data cached forever - may become stale
await env.CACHE.put(cacheKey, data);
}
}
// ✅ Correct: Appropriate TTL strategy
export default {
async fetch(request: Request, env: Env) {
const cacheKey = 'user:profile:123';
// Cache user profile for 1 hour (reasonable for user data)
await env.CACHE.put(cacheKey, data, {
expirationTtl: 3600 // 1 hour
});
// Cache API response for 5 minutes (frequently changing)
await env.API_CACHE.put(apiKey, response, {
expirationTtl: 300 // 5 minutes
});
// Cache static data for 24 hours (rarely changes)
await env.STATIC_CACHE.put(staticKey, data, {
expirationTtl: 86400 // 24 hours
});
}
}
```
### Fixing Large Value Handling
```typescript
// ❌ High: Large values approaching KV limits
export default {
async fetch(request: Request, env: Env) {
const reportId = new URL(request.url).searchParams.get('id');
// Large report (20MB) - close to KV 25MB limit!
const report = await env.REPORTS.get(reportId);
return new Response(report);
}
}
// ✅ Correct: Compress large values or use R2
export default {
async fetch(request: Request, env: Env) {
const reportId = new URL(request.url).searchParams.get('id');
// Option 1: Compress before storing in KV
const compressed = await env.REPORTS.get(reportId);
const decompressed = decompress(compressed);
// Option 2: Use R2 for large objects
const object = await env.REPORTS_BUCKET.get(reportId);
return new Response(object.body);
}
}
```
## Storage Choice Guidance
### Use KV When:
- **Small values** (< 1MB typical, < 25MB max)
- **Key-value access patterns**
- **Eventually consistent** data is acceptable
- **Low latency** reads required globally
- **Simple caching** needs
### Use R2 When:
- **Large objects** (files, images, videos)
- **S3-compatible** access needed
- **Strong consistency** required
- **Object storage** patterns
- **Large files** (> 1MB)
### Use D1 When:
- **Relational data** with complex queries
- **Strong consistency** required
- **SQL operations** needed
- **Structured data** with relationships
- **Complex queries** and joins
## MCP Server Integration
When Cloudflare MCP server is available:
- Query KV performance metrics (latency, hit rates)
- Analyze storage usage patterns
- Get latest KV optimization techniques
- Check storage limits and quotas
## Benefits
### Immediate Impact
- **Faster Response Times**: Parallel operations reduce latency by 3x or more
- **Reduced KV Costs**: Fewer operations and better caching
- **Better Performance**: Proper storage choice improves overall performance
### Long-term Value
- **Consistent Optimization**: Ensures all KV usage follows best practices
- **Cost Efficiency**: Optimized storage patterns reduce costs
- **Better User Experience**: Faster response times from optimized storage
## Usage Examples
### During KV Operation Writing
```typescript
// Developer types: sequential KV gets
// SKILL immediately activates: "⚠️ HIGH: Sequential KV operations detected. Use Promise.all() to parallelize and reduce latency by 3x."
```
### During Storage Architecture
```typescript
// Developer types: storing large files in KV
// SKILL immediately activates: "⚠️ HIGH: Large file storage in KV detected. Use R2 for objects > 1MB to avoid performance issues."
```
### During Caching Implementation
```typescript
// Developer types: repeated KV calls in same request
// SKILL immediately activates: "⚠️ HIGH: Duplicate KV calls detected. Add request-scoped caching to avoid redundant network calls."
```
## Performance Targets
### KV Operation Latency
- **Excellent**: < 10ms (parallel operations)
- **Good**: < 30ms (single operation)
- **Acceptable**: < 100ms (sequential operations)
- **Needs Improvement**: > 100ms
### Cache Hit Rate
- **Excellent**: > 90%
- **Good**: > 75%
- **Acceptable**: > 50%
- **Needs Improvement**: < 50%
This SKILL ensures KV storage performance by providing immediate, autonomous optimization of storage patterns, preventing common performance issues and ensuring efficient data access.