Back to list
jeremylongshore

juicebox-rate-limits

by jeremylongshore

Hundreds of Claude Code plugins with embedded AI skills. Learn via interactive Jupyter tutorials.

1,042🍴 135📅 Jan 23, 2026

SKILL.md


name: juicebox-rate-limits description: | 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

Juicebox Rate Limits

Overview

Understand and implement proper rate limiting handling for Juicebox API.

Rate Limit Tiers

PlanRequests/MinRequests/DaySearches/Month
Free10100500
Pro605,00025,000
Enterprise30050,000Unlimited

Instructions

Step 1: Understand Rate Limit Headers

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

// lib/rate-limiter.ts
export class RateLimiter {
  private queue: Array<() => Promise<void>> = [];
  private processing = false;
  private lastRequestTime = 0;
  private minInterval: number;

  constructor(requestsPerMinute: number) {
    this.minInterval = 60000 / requestsPerMinute;
  }

  async execute<T>(fn: () => Promise<T>): Promise<T> {
    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

// lib/backoff.ts
export async function withExponentialBackoff<T>(
  fn: () => Promise<T>,
  options: {
    maxRetries?: number;
    baseDelay?: number;
    maxDelay?: number;
  } = {}
): Promise<T> {
  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

// lib/quota-tracker.ts
export class QuotaTracker {
  private dailyRequests = 0;
  private dailyResetTime: Date;

  constructor(private dailyLimit: number) {
    this.dailyResetTime = this.getNextMidnight();
  }

  async checkQuota(): Promise<boolean> {
    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

ScenarioStrategy
429 with Retry-AfterWait exact duration
429 without Retry-AfterExponential backoff
Approaching limitProactive throttling
Daily quota exhaustedQueue for next day

Resources

Next Steps

After rate limit handling, see juicebox-security-basics for security best practices.

Score

Total Score

85/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 1000以上

+15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

+5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon