API Rate Limits
Teabar enforces rate limits to ensure fair usage and platform stability. This guide covers rate limit policies, quotas, and best practices.
Rate Limit Overview
Rate limits are applied per API key or user:
| Plan | Requests/Minute | Requests/Day | Burst |
|---|---|---|---|
| Free | 60 | 10,000 | 100 |
| Pro | 300 | 100,000 | 500 |
| Enterprise | 1,000 | Unlimited | 2,000 |
Note
**Burst** allows temporary spikes above the per-minute limit. Burst capacity refills over time.
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 250
X-RateLimit-Reset: 1710086400 | Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when limit resets |
Rate Limit Response
When rate limited, the API returns:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 30
{
"code": "resource_exhausted",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"details": [{
"@type": "type.googleapis.com/google.rpc.RetryInfo",
"retryDelay": "30s"
}]
} Per-Endpoint Limits
Some endpoints have additional specific limits:
| Endpoint | Limit | Notes |
|---|---|---|
CreateEnvironment | 10/min | Environment creation is resource-intensive |
WatchEnvironment | 20 concurrent | Streaming connections |
SearchCatalog | 30/min | Search queries |
ValidateBlueprint | 30/min | Validation requests |
Resource Quotas
Beyond rate limits, resource quotas apply:
Environment Quotas
| Plan | Concurrent Environments | Environments/Month |
|---|---|---|
| Free | 2 | 10 |
| Pro | Unlimited* | Unlimited |
| Enterprise | Unlimited* | Unlimited |
*Subject to compute quotas
Compute Quotas
| Plan | vCPU-hours/month | Memory GB-hours/month |
|---|---|---|
| Free | 100 | 200 |
| Pro | Based on subscription | Based on subscription |
| Enterprise | Custom | Custom |
Handling Rate Limits
Check Before Limiting
function checkRateLimit(response: Response) {
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining') || '0');
const resetTime = parseInt(response.headers.get('X-RateLimit-Reset') || '0');
if (remaining < 10) {
console.warn(`Rate limit nearly exhausted. ${remaining} requests remaining.`);
console.warn(`Resets at ${new Date(resetTime * 1000).toISOString()}`);
}
} Implement Retry Logic
async function apiCall(request: () => Promise<Response>): Promise<Response> {
let attempts = 0;
const maxAttempts = 3;
while (attempts < maxAttempts) {
const response = await request();
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
console.log(`Rate limited. Retrying in ${retryAfter}s...`);
await sleep(retryAfter * 1000);
attempts++;
continue;
}
return response;
}
throw new Error('Max retry attempts exceeded');
} Exponential Backoff
async function exponentialBackoff<T>(
fn: () => Promise<T>,
maxAttempts: number = 5
): Promise<T> {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
if (error.code === 'resource_exhausted' && attempt < maxAttempts - 1) {
const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
await sleep(delay);
} else {
throw error;
}
}
}
throw new Error('Max attempts reached');
} Best Practices
Request Optimization
- Batch operations - Use bulk endpoints when available
- Cache responses - Cache read-only data locally
- Use pagination - Fetch only needed data
- Avoid polling - Use streaming endpoints for real-time data
Caching Strategies
const cache = new Map<string, { data: any; expires: number }>();
async function cachedGet(key: string, fetcher: () => Promise<any>, ttl: number = 60000) {
const cached = cache.get(key);
if (cached && cached.expires > Date.now()) {
return cached.data;
}
const data = await fetcher();
cache.set(key, { data, expires: Date.now() + ttl });
return data;
} Use Streaming for Real-time Data
Instead of polling:
// Bad: Polling every 5 seconds
setInterval(async () => {
const env = await client.getEnvironment({ environmentId: "env_abc" });
updateUI(env);
}, 5000);
// Good: Use streaming
const stream = client.watchEnvironment({ environmentId: "env_abc" });
for await (const event of stream) {
updateUI(event.environment);
} Monitoring Usage
Via API
curl -H "Authorization: Bearer $TOKEN"
https://api.teabar.dev/teabar.v1.UsageService/GetUsage Response:
{
"apiUsage": {
"requestsToday": 4523,
"requestsThisMonth": 45230,
"limits": {
"requestsPerMinute": 300,
"requestsPerDay": 100000
}
},
"resourceUsage": {
"environments": 8,
"vcpuHours": 234.5,
"memoryGbHours": 567.8
}
} Via Web Console
- Go to Organization Settings > Usage
- View API and resource usage dashboards
- Set up usage alerts
Increasing Limits
Pro Plan
Upgrade to Pro for higher limits:
- 300 requests/minute
- 100,000 requests/day
- No environment count limits
Enterprise
For custom limits:
- Contact sales for negotiated limits
- SLA guarantees
- Dedicated infrastructure options
Temporary Increases
For special events (workshops, demos):
- Contact support in advance
- Provide expected usage details
- Temporary limit increases may be granted
Troubleshooting
Frequent Rate Limiting
- Check for loops - Ensure no infinite retry loops
- Review request patterns - Identify unnecessary requests
- Implement caching - Reduce redundant fetches
- Use bulk operations - Batch where possible
Unexpected Quota Usage
- Audit API keys - Check for unauthorized usage
- Review scripts - Identify runaway automation
- Check activity logs - See who’s making requests
See Also
- API Errors - Error handling
- API Authentication - Authentication methods
- Pricing - Plan details and limits