| 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
interface RateLimitHeaders {
'x-ratelimit-limit': string;
'x-ratelimit-remaining': string;
'x-ratelimit-reset': string;
'retry-after'?: string;
}
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
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() {
(. || .. === ) ;
. = ;
(.. > ) {
now = .();
elapsed = now - .;
(elapsed < .) {
(. - elapsed);
}
task = ..();
(task) {
. = .();
();
}
}
. = ;
}
}
Step 3: Add Exponential Backoff
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();
(delay);
;
}
error;
}
}
lastError!;
}
Step 4: Implement Quota Tracking
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) {
. = ;
. = .();
}
}
}
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
Next Steps
After rate limit handling, see juicebox-security-basics for security best practices.