Marketplace

kv-optimization-advisor

Automatically optimizes Cloudflare KV storage patterns, suggesting parallel operations, caching strategies, and storage choice guidance

$ Instalar

git clone https://github.com/hirefrank/hirefrank-marketplace /tmp/hirefrank-marketplace && cp -r /tmp/hirefrank-marketplace/plugins/edge-stack/skills/kv-optimization-advisor ~/.claude/skills/hirefrank-marketplace

// tip: Run this command in your terminal to install the skill


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

// 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-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

// ❌ 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.

Repository

hirefrank
hirefrank
Author
hirefrank/hirefrank-marketplace/plugins/edge-stack/skills/kv-optimization-advisor
2
Stars
0
Forks
Updated2d ago
Added1w ago