cloudflare-api-orchestration

majiayu000's avatarfrom majiayu000

Activates automatically when designing or implementing Cloudflare Workers APIs,orchestrating multi-provider API calls, implementing D1 database operations,or managing KV-based caching strategies.Ensures proper error handling, provider tagging, fallback chains, andorchestration patterns for BooksTrack backend infrastructure.Auto-activates on:- File patterns: *.worker.js, *-api.ts, *-service.ts in backend code- Keywords: "api orchestration", "multi-provider", "fallback chain", "D1 query"- Context: Cloudflare Workers development, API design discussions

⭐5stars🔀1forks📁View on GitHub🕐Updated Jan 11, 2026

When & Why to Use This Skill

This Claude skill optimizes the development of Cloudflare Workers by enforcing robust API orchestration patterns. It automates the creation of multi-provider fallback chains, secure D1 database queries, and efficient KV caching strategies, ensuring high availability and performance for backend infrastructure. By implementing mandatory provider tagging and circuit breaker patterns, it helps developers build resilient, production-ready APIs that handle failures gracefully.

Use Cases

  • Case 1: Designing multi-provider API orchestrators that automatically switch to fallback services or cache during primary provider outages to ensure 100% uptime.
  • Case 2: Implementing secure Cloudflare D1 database operations using prepared statements and batch processing to prevent SQL injection and optimize query performance.
  • Case 3: Developing high-performance caching layers with Cloudflare KV using standardized naming conventions and TTL-based expiration to reduce external API costs and latency.
  • Case 4: Integrating advanced reliability patterns like Circuit Breakers and Rate Limiting to protect backend services from cascading failures and high-traffic abuse.
namecloudflare-api-orchestration
description|
- File patterns*.worker.js, *-api.ts, *-service.ts in backend code
- Keywords"api orchestration", "multi-provider", "fallback chain", "D1 query"
- ContextCloudflare Workers development, API design discussions
allowed-tools["Read", "Grep", "Edit", "Write", "WebFetch"]

Cloudflare API Orchestration Skill

This skill enforces BooksTrack-specific API orchestration patterns for Cloudflare Workers.

Core Principles

1. Provider Orchestration (MANDATORY)

NEVER make direct API calls without orchestration layer.

Correct pattern:

// orchestrator.js
export class APIOrchestrator {
  async searchBooks(query, options = {}) {
    const providers = [
      { name: 'google', fn: () => this.googleBooks.search(query) },
      { name: 'openlibrary', fn: () => this.openLibrary.search(query) }
    ];

    for (const provider of providers) {
      try {
        const result = await provider.fn();
        return {
          ...result,
          provider: `orchestrated:${providers.map(p => p.name).join('+')}`,
          cached: false
        };
      } catch (error) {
        console.warn(`Provider ${provider.name} failed:`, error);
        continue;
      }
    }

    // Final fallback to cache
    const cached = await this.kv.get(`book:${query}`);
    if (cached) {
      return {
        ...JSON.parse(cached),
        provider: 'cache:kv',
        cached: true
      };
    }

    throw new Error('All providers failed');
  }
}

Wrong pattern (FORBIDDEN):

// ❌ Direct API call without orchestration
async function searchBooks(query) {
  const response = await fetch(`https://www.googleapis.com/books/v1/volumes?q=${query}`);
  return response.json(); // Missing provider tag, no fallback, no caching
}

2. Provider Tagging (REQUIRED)

All responses MUST include provider metadata:

{
  data: { /* actual response */ },
  provider: "orchestrated:google+openlibrary", // Multi-provider
  cached: false,
  timestamp: Date.now()
}

Tag formats:

  • "orchestrated:google+openlibrary" - Successful multi-provider aggregation
  • "google" - Single provider (fallback failed or only one available)
  • "cache:kv" - Retrieved from KV cache
  • "cache:d1" - Retrieved from D1 database

3. Error Handling Patterns

Implement graceful degradation:

try {
  // Primary provider
  const result = await primaryProvider.fetch();
  return { data: result, provider: 'primary', cached: false };
} catch (primaryError) {
  console.warn('Primary provider failed:', primaryError);

  try {
    // Secondary provider
    const result = await secondaryProvider.fetch();
    return { data: result, provider: 'secondary', cached: false };
  } catch (secondaryError) {
    console.warn('Secondary provider failed:', secondaryError);

    // Cache fallback
    const cached = await cache.get(key);
    if (cached) {
      return { data: cached, provider: 'cache:kv', cached: true };
    }

    // Final error with context
    throw new APIError('All providers exhausted', {
      primaryError,
      secondaryError,
      key
    });
  }
}

4. D1 Query Patterns

Always use prepared statements:

// ✅ Correct - prepared statement
const result = await env.DB.prepare(
  'SELECT * FROM books WHERE isbn = ?'
).bind(isbn).first();

// ❌ Wrong - SQL injection vulnerability
const result = await env.DB.prepare(
  `SELECT * FROM books WHERE isbn = '${isbn}'`
).first();

Batch operations for efficiency:

// ✅ Correct - batch insert
const stmt = env.DB.prepare('INSERT INTO books (isbn, title) VALUES (?, ?)');
const batch = books.map(book => stmt.bind(book.isbn, book.title));
await env.DB.batch(batch);

// ❌ Wrong - individual inserts (slow)
for (const book of books) {
  await env.DB.prepare('INSERT INTO books (isbn, title) VALUES (?, ?)')
    .bind(book.isbn, book.title)
    .run();
}

5. KV Caching Strategy

Key naming convention:

namespace:entity:id

Examples:

  • book:isbn:9780134685991
  • search:query:swift+programming
  • user:profile:user123

Caching pattern:

async function getCachedOrFetch(key, fetchFn, ttl = 3600) {
  // Try cache first
  const cached = await env.KV.get(key, { type: 'json' });
  if (cached) {
    return { ...cached, cached: true };
  }

  // Fetch from provider
  const fresh = await fetchFn();

  // Cache for TTL seconds
  await env.KV.put(key, JSON.stringify(fresh), {
    expirationTtl: ttl,
    metadata: { cached_at: Date.now() }
  });

  return { ...fresh, cached: false };
}

6. Rate Limiting

Implement per-endpoint rate limits:

import { RateLimiter } from './rate-limiter';

const limiter = new RateLimiter({
  search: { requests: 100, window: 60 }, // 100 req/min
  details: { requests: 200, window: 60 }  // 200 req/min
});

async function handleSearch(request, env) {
  const clientId = request.headers.get('CF-Connecting-IP');

  if (!await limiter.check('search', clientId)) {
    return new Response('Rate limit exceeded', {
      status: 429,
      headers: {
        'Retry-After': '60',
        'X-RateLimit-Limit': '100',
        'X-RateLimit-Remaining': '0'
      }
    });
  }

  // Process request...
}

7. Circuit Breaker Pattern

Prevent cascading failures:

class CircuitBreaker {
  constructor(threshold = 5, timeout = 60000) {
    this.failureCount = 0;
    this.threshold = threshold;
    this.timeout = timeout;
    this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
    this.nextAttempt = Date.now();
  }

  async call(fn) {
    if (this.state === 'OPEN') {
      if (Date.now() < this.nextAttempt) {
        throw new Error('Circuit breaker OPEN');
      }
      this.state = 'HALF_OPEN';
    }

    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }

  onSuccess() {
    this.failureCount = 0;
    this.state = 'CLOSED';
  }

  onFailure() {
    this.failureCount++;
    if (this.failureCount >= this.threshold) {
      this.state = 'OPEN';
      this.nextAttempt = Date.now() + this.timeout;
    }
  }
}

BooksTrack-Specific Patterns

Book Search API

// Route: GET /api/v2/books/search?q=...
export async function handleBookSearch(request, env) {
  const url = new URL(request.url);
  const query = url.searchParams.get('q');

  if (!query) {
    return new Response(JSON.stringify({ error: 'Missing query parameter' }), {
      status: 400,
      headers: { 'Content-Type': 'application/json' }
    });
  }

  const orchestrator = new APIOrchestrator(env);

  try {
    const result = await orchestrator.searchBooks(query);
    return new Response(JSON.stringify(result), {
      status: 200,
      headers: {
        'Content-Type': 'application/json',
        'Cache-Control': 'public, max-age=3600',
        'X-Provider': result.provider
      }
    });
  } catch (error) {
    console.error('Search failed:', error);
    return new Response(JSON.stringify({
      error: 'Search failed',
      message: error.message
    }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' }
    });
  }
}

Book Details API

// Route: GET /api/v2/books/:isbn
export async function handleBookDetails(isbn, env) {
  // Try D1 first (authoritative source)
  const cached = await env.DB.prepare(
    'SELECT * FROM books WHERE isbn = ?'
  ).bind(isbn).first();

  if (cached) {
    return {
      ...cached,
      provider: 'cache:d1',
      cached: true
    };
  }

  // Fetch from providers
  const orchestrator = new APIOrchestrator(env);
  const result = await orchestrator.getBookByISBN(isbn);

  // Store in D1 for future requests
  await env.DB.prepare(
    'INSERT OR REPLACE INTO books (isbn, title, author, data) VALUES (?, ?, ?, ?)'
  ).bind(isbn, result.title, result.author, JSON.stringify(result)).run();

  return result;
}

Anti-Patterns to Avoid

❌ Direct API Calls

// DON'T DO THIS
const response = await fetch('https://api.example.com/books');

❌ Missing Provider Tags

// DON'T DO THIS
return { data: books }; // Missing provider metadata

❌ Unhandled Errors

// DON'T DO THIS
const result = await provider.fetch(); // No try-catch

❌ SQL Injection Vulnerabilities

// DON'T DO THIS
await env.DB.prepare(`SELECT * FROM books WHERE title = '${title}'`).first();

❌ No Caching Strategy

// DON'T DO THIS - always hitting live APIs
const result = await provider.fetch(); // No cache check

Validation Checklist

When implementing or reviewing Cloudflare Workers APIs, verify:

  • All API calls go through orchestration layer
  • Responses include provider tags
  • Fallback chains implemented (primary → secondary → cache)
  • D1 queries use prepared statements
  • KV keys follow naming convention
  • Rate limiting configured for public endpoints
  • Circuit breakers protect external services
  • Error handling provides useful context
  • Caching strategy reduces API calls
  • Logging captures provider failures

Integration with Code Review

This skill complements the code-review-grok subagent. When code review identifies orchestration violations, this skill provides the correct patterns to follow.


Async API Development (v2.0.64)

Complex API implementations can run in background:

// Launch complex endpoint implementation in background
Task({
  subagent_type: "cloudflare-specialist",
  prompt: "Implement /api/v3/books/search with full orchestration, caching, rate limiting",
  run_in_background: true
})

// Continue with other work (UI, tests)...

// Retrieve implementation when ready
TaskOutput({
  task_id: "agent_xyz123",
  block: true
})

Background-friendly tasks:

  • Complex multi-provider orchestration
  • D1 schema migrations
  • KV→D1 data migrations
  • Comprehensive API security audits

Recommended Option Pattern (v2.0.62):

When presenting API implementation choices:

options: [
  {label: "Orchestrated (Recommended)", description: "Multi-provider with fallback"},
  {label: "Single provider", description: "Google Books only"},
  {label: "Cache-first", description: "D1/KV with lazy provider fetch"}
]

Last Updated: December 11, 2025 Maintained by: Claude Code PM System Related Agents: cloudflare-specialist, code-review-grok Claude Code Version: v2.0.65