Examples
Advanced Configuration
Advanced usage patterns with tiered rate limiting, dynamic limits, and complex scenarios.
Advanced Configuration
Advanced patterns for complex rate limiting scenarios.
Tiered Rate Limiting
import { createClient } from 'limitly-sdk';
const client = createClient({ serviceId: 'tiered-api' });
const tierLimits = {
free: { capacity: 100, refillRate: 10 },
pro: { capacity: 1000, refillRate: 100 },
enterprise: { capacity: 10000, refillRate: 1000 }
};
async function checkTieredLimit(user: User, endpoint?: string) {
if (user.isAdmin) {
return { allowed: true, limit: Infinity, remaining: Infinity };
}
const limits = tierLimits[user.plan];
return await client.checkRateLimit({
identifier: `${user.id}:${endpoint || 'default'}`,
...limits
});
}Dynamic Rate Limiting
import { createClient } from 'limitly-sdk';
const client = createClient({ serviceId: 'adaptive-api' });
// Simulate system load monitoring
async function getSystemLoad(): Promise<number> {
// In real implementation, get from your monitoring system
// Returns 0-100 representing CPU/memory usage
return Math.random() * 100;
}
async function checkAdaptiveLimit(userId: string) {
const systemLoad = await getSystemLoad();
// Reduce limits when system is under heavy load
const baseCapacity = 100;
const baseRefillRate = 10;
const capacity = systemLoad > 80
? Math.floor(baseCapacity * 0.5) // 50% capacity under high load
: systemLoad > 50
? Math.floor(baseCapacity * 0.75) // 75% capacity under medium load
: baseCapacity; // Full capacity under normal load
const refillRate = systemLoad > 80
? Math.floor(baseRefillRate * 0.5)
: systemLoad > 50
? Math.floor(baseRefillRate * 0.75)
: baseRefillRate;
return await client.checkRateLimit({
identifier: userId,
capacity,
refillRate
});
}Time-Based Limiting
function getTimeBasedLimits() {
const hour = new Date().getHours();
return hour >= 9 && hour < 17
? { capacity: 50, refillRate: 5 } // Peak hours
: { capacity: 200, refillRate: 20 }; // Off-peak
}
await client.checkRateLimit({ identifier: userId, ...getTimeBasedLimits() });Geographic Limiting
const regionLimits = {
'US': { capacity: 100, refillRate: 10 },
'ASIA': { capacity: 200, refillRate: 20 },
'DEFAULT': { capacity: 50, refillRate: 5 }
};
const limits = regionLimits[country] || regionLimits['DEFAULT'];
await client.checkRateLimit({ identifier: `${userId}:${country}`, ...limits });Multiple Windows
import { createClient } from 'limitly-sdk';
const client = createClient({ serviceId: 'multi-window' });
async function checkMultiWindowLimit(userId: string) {
// Check multiple time windows
const [minuteResult, hourResult, dayResult] = await Promise.all([
// Per-minute limit
client.checkRateLimit({
identifier: `${userId}:minute`,
capacity: 10,
refillRate: 10,
window: 60000 // 1 minute
}),
// Per-hour limit
client.checkRateLimit({
identifier: `${userId}:hour`,
capacity: 1000,
refillRate: 1000 / 3600, // ~0.28 per second
window: 3600000 // 1 hour
}),
// Per-day limit
client.checkRateLimit({
identifier: `${userId}:day`,
capacity: 10000,
refillRate: 10000 / 86400, // ~0.12 per second
window: 86400000 // 1 day
})
]);
// Request is allowed only if all windows allow it
const allowed = minuteResult.allowed && hourResult.allowed && dayResult.allowed;
return {
allowed,
windows: {
minute: minuteResult,
hour: hourResult,
day: dayResult
},
// Return the most restrictive remaining count
remaining: Math.min(
minuteResult.remaining ?? Infinity,
hourResult.remaining ?? Infinity,
dayResult.remaining ?? Infinity
)
};
}Burst Protection
Allow bursts but limit sustained traffic:
import { createClient } from 'limitly-sdk';
const client = createClient({ serviceId: 'burst-protection' });
async function checkBurstLimit(userId: string) {
// Short window for burst detection
const burstResult = await client.checkRateLimit({
identifier: `${userId}:burst`,
capacity: 20, // Allow 20 requests
refillRate: 20, // Refill 20 per second
window: 1000 // 1 second window
});
// Longer window for sustained rate
const sustainedResult = await client.checkRateLimit({
identifier: `${userId}:sustained`,
capacity: 100, // 100 requests
refillRate: 10, // Refill 10 per second
window: 10000 // 10 second window
});
// Allow if either window allows (OR logic)
// Or require both (AND logic) - current implementation
const allowed = burstResult.allowed && sustainedResult.allowed;
return {
allowed,
burst: burstResult,
sustained: sustainedResult
};
}Rate Limit with Exponential Backoff
Implement exponential backoff for rate-limited users:
import { createClient } from 'limitly-sdk';
const client = createClient({ serviceId: 'backoff' });
interface RateLimitState {
attempts: number;
lastAttempt: number;
}
async function checkWithBackoff(userId: string): Promise<{
allowed: boolean;
backoffSeconds?: number;
result: any;
}> {
// Check standard rate limit
const result = await client.checkRateLimit({
identifier: userId,
capacity: 100,
refillRate: 10
});
if (result.allowed) {
return { allowed: true, result };
}
// Calculate exponential backoff
// Get previous attempt count from cache or database
const state: RateLimitState = await getRateLimitState(userId);
const attempts = state.attempts + 1;
// Exponential backoff: 2^attempts seconds, max 60 seconds
const backoffSeconds = Math.min(Math.pow(2, attempts), 60);
// Store state
await setRateLimitState(userId, {
attempts,
lastAttempt: Date.now()
});
return {
allowed: false,
backoffSeconds,
result: {
...result,
message: `Rate limited. Please retry after ${backoffSeconds} seconds.`,
retryAfter: backoffSeconds
}
};
}
// Helper functions (implement with your cache/database)
async function getRateLimitState(userId: string): Promise<RateLimitState> {
// Get from Redis, database, etc.
return { attempts: 0, lastAttempt: 0 };
}
async function setRateLimitState(userId: string, state: RateLimitState): Promise<void> {
// Store in Redis, database, etc.
}