juicebox-rate-limits

Implement Juicebox rate limiting and backoff. Use when handling API quotas, implementing retry logic, or optimizing request throughput. Trigger with phrases like "juicebox rate limit", "juicebox quota", "juicebox throttling", "juicebox backoff". allowed-tools: Read, Grep, Bash(curl:*) version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>

Allowed Tools

No tools specified

Provided by Plugin

juicebox-pack

Claude Code skill pack for Juicebox (24 skills)

saas packs v1.0.0
View Plugin

Installation

This skill is included in the juicebox-pack plugin:

/plugin install juicebox-pack@claude-code-plugins-plus

Click to copy

Instructions

# Juicebox Rate Limits ## Overview Understand and implement proper rate limiting handling for Juicebox API. ## Rate Limit Tiers | Plan | Requests/Min | Requests/Day | Searches/Month | |------|--------------|--------------|----------------| | Free | 10 | 100 | 500 | | Pro | 60 | 5,000 | 25,000 | | Enterprise | 300 | 50,000 | Unlimited | ## Instructions ### Step 1: Understand Rate Limit Headers ```typescript // Juicebox returns these headers with every response interface RateLimitHeaders { 'x-ratelimit-limit': string; // Max requests per window 'x-ratelimit-remaining': string; // Remaining requests 'x-ratelimit-reset': string; // Unix timestamp when limit resets 'retry-after'?: string; // Seconds to wait (only on 429) } function parseRateLimitHeaders(headers: Headers) { return { limit: parseInt(headers.get('x-ratelimit-limit') || '0'), remaining: parseInt(headers.get('x-ratelimit-remaining') || '0'), reset: new Date(parseInt(headers.get('x-ratelimit-reset') || '0') * 1000), retryAfter: parseInt(headers.get('retry-after') || '0') }; } ``` ### Step 2: Implement Rate Limiter ```typescript // lib/rate-limiter.ts export class RateLimiter { private queue: Array<() => Promise> = []; private processing = false; private lastRequestTime = 0; private minInterval: number; constructor(requestsPerMinute: number) { this.minInterval = 60000 / requestsPerMinute; } async execute(fn: () => Promise): Promise { return new Promise((resolve, reject) => { this.queue.push(async () => { try { const result = await fn(); resolve(result); } catch (error) { reject(error); } }); this.processQueue(); }); } private async processQueue() { if (this.processing || this.queue.length === 0) return; this.processing = true; while (this.queue.length > 0) { const now = Date.now(); const elapsed = now - this.lastRequestTime; if (elapsed < this.minInterval) { await sleep(this.minInterval - elapsed); } const task = this.queue.shift(); if (task) { this.lastRequestTime = Date.now(); await task(); } } this.processing = false; } } ``` ### Step 3: Add Exponential Backoff ```typescript // lib/backoff.ts export async function withExponentialBackoff( fn: () => Promise, options: { maxRetries?: number; baseDelay?: number; maxDelay?: number; } = {} ): Promise { const { maxRetries = 5, baseDelay = 1000, maxDelay = 60000 } = options; let lastError: Error; for (let attempt = 0; attempt < maxRetries; attempt++) { try { return await fn(); } catch (error: any) { lastError = error; if (error.code === 'RATE_LIMITED') { const retryAfter = error.retryAfter || 0; const backoffDelay = Math.min( baseDelay * Math.pow(2, attempt), maxDelay ); const delay = Math.max(retryAfter * 1000, backoffDelay); console.log(`Rate limited. Retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`); await sleep(delay); continue; } throw error; } } throw lastError!; } ``` ### Step 4: Implement Quota Tracking ```typescript // lib/quota-tracker.ts export class QuotaTracker { private dailyRequests = 0; private dailyResetTime: Date; constructor(private dailyLimit: number) { this.dailyResetTime = this.getNextMidnight(); } async checkQuota(): Promise { this.maybeResetDaily(); return this.dailyRequests < this.dailyLimit; } recordRequest() { this.dailyRequests++; } getRemainingQuota(): number { this.maybeResetDaily(); return this.dailyLimit - this.dailyRequests; } private maybeResetDaily() { if (new Date() > this.dailyResetTime) { this.dailyRequests = 0; this.dailyResetTime = this.getNextMidnight(); } } } ``` ## Output - Rate limiter with queue - Exponential backoff handler - Quota tracking system - Header parsing utilities ## Error Handling | Scenario | Strategy | |----------|----------| | 429 with Retry-After | Wait exact duration | | 429 without Retry-After | Exponential backoff | | Approaching limit | Proactive throttling | | Daily quota exhausted | Queue for next day | ## Resources - [Rate Limits Documentation](https://juicebox.ai/docs/rate-limits) - [Quota Dashboard](https://app.juicebox.ai/usage) ## Next Steps After rate limit handling, see `juicebox-security-basics` for security best practices.

Skill file: plugins/saas-packs/juicebox-pack/skills/juicebox-rate-limits/SKILL.md