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".
Scanned 9/1/2026
Install to Claude Code
npx -y skills add Dicklesworthstone/pi_agent_rust --skill juicebox-rate-limits --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Juicebox Rate Limits?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/dicklesworthstone-juicebox-rate-limits)More formats (shields.io, HTML) on the badges page.
---
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
| 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<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
```typescript
// 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
```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<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
| 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.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!