Agent skill
kv-optimization-advisor
Automatically optimizes Cloudflare KV storage patterns, suggesting parallel operations, caching strategies, and storage choice guidance
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/design/kv-optimization-advisor
SKILL.md
KV Optimization Advisor SKILL
Activation Patterns
This SKILL automatically activates when:
- KV
get,put,delete, orlistoperations 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
// 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
// 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-strategistagent - KV performance troubleshooting →
edge-performance-oracleagent - Storage migration strategies →
cloudflare-architecture-strategistagent
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
// ❌ 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
// ❌ 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
// ❌ 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
// ❌ 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
// ❌ 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
// 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
// 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
// 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.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?