Back to Blog
EngineeringJanuary 7, 20256 min read

API Rate Limiting Best Practices for Esports Apps

How to handle rate limits gracefully, implement caching strategies, and keep your app responsive under load.

Share:

Understanding Rate Limits

Every API has rate limits. Cito API's limits vary by plan:

  • Free: 10 requests/minute
  • Basic: 30 requests/minute
  • Pro: 100 requests/minute
  • Business: 500 requests/minute

Hitting these limits returns a 429 status code. Here's how to handle them gracefully.

Implementing Retry Logic

async function fetchWithRetry(url, options, maxRetries = 3) {

for (let i = 0; i < maxRetries; i++) {

const response = await fetch(url, options);

if (response.status === 429) {

const retryAfter = response.headers.get('Retry-After') || 60;

await sleep(retryAfter * 1000);

continue;

}

return response;

}

throw new Error('Max retries exceeded');

}

Caching Strategies

In-Memory Cache (Simple)

const cache = new Map();

async function getCachedData(key, fetchFn, ttl = 30000) {

const cached = cache.get(key);

if (cached && Date.now() - cached.timestamp < ttl) {

return cached.data;

}

const data = await fetchFn();

cache.set(key, { data, timestamp: Date.now() });

return data;

}

Redis Cache (Production)

const redis = new Redis(process.env.REDIS_URL);

async function getCachedData(key, fetchFn, ttl = 30) {

const cached = await redis.get(key);

if (cached) {

return JSON.parse(cached);

}

const data = await fetchFn();

await redis.setex(key, ttl, JSON.stringify(data));

return data;

}

Request Batching

Instead of making individual requests:

// Bad: 10 requests

for (const playerId of playerIds) {

await api.get(/players/${playerId});

}

// Good: 1 request

const players = await api.get('/players', {

params: { ids: playerIds.join(',') }

});

Using Webhooks Instead

For real-time data, webhooks are more efficient than polling:

// Instead of polling every 30 seconds

setInterval(fetchLiveMatches, 30000);

// Use webhooks (Pro plan and above)

app.post('/webhook', (req, res) => {

const { event, data } = req.body;

handleMatchUpdate(data);

res.status(200).send('OK');

});

Monitoring Your Usage

Check your current usage via the dashboard or API:

const response = await api.get('/account/usage');

console.log(Used: ${response.data.requests_used});

console.log(Limit: ${response.data.requests_limit});

Conclusion

Good rate limit handling makes your app more reliable and your users happier. Implement caching, use webhooks where possible, and always handle 429s gracefully.

View our rate limit documentation

Ready to Build?

Get your API key and start building with esports data in minutes.