| name | algolia-rate-limits |
| description | Handle Algolia rate limits and throttling: per-key limits, indexing queue limits,
429 responses, and backoff strategies.
Trigger: "algolia rate limit", "algolia throttling", "algolia 429",
"algolia retry", "algolia backoff", "algolia too many requests".
|
| allowed-tools | Read, Write, Edit |
| version | 1.6.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| tags | ["saas","search","algolia"] |
| compatibility | Designed for Claude Code |
Algolia Rate Limits
Overview
Algolia has two distinct rate limiting mechanisms: per-API-key limits (configurable, returns HTTP 429) and server-side indexing limits (protects cluster stability, returns HTTP 429 with specific messages). The algoliasearch v5 client has built-in retry with backoff, but you need to handle sustained rate limiting yourself.
How Algolia Rate Limiting Works
Per-API-Key Rate Limits
| Setting | Default | Where to Change |
|---|
maxQueriesPerIPPerHour | 0 (unlimited) | Dashboard > API Keys > Edit |
maxHitsPerQuery | 1000 | Dashboard > API Keys > Edit |
| Search requests | Plan-dependent | Upgrade plan |
Server-Side Indexing Limits
When the indexing queue is overloaded, Algolia returns 429 with these messages:
| Message | Meaning | Action |
|---|
Too many jobs | Queue full | Reduce batch frequency |
Job queue too large | Too much pending work | Wait for queue to drain |
Old jobs on the queue | Stuck tasks | Check dashboard > Indices > Operations |
Disk almost full | Record quota near limit | Delete unused records or upgrade |
Instructions
Step 1: Configure Per-Key Rate Limits
import { algoliasearch } from 'algoliasearch';
const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);
const { key } = await client.addApiKey({
apiKey: {
acl: ['search'],
description: 'Frontend search key — rate limited',
maxQueriesPerIPPerHour: 1000,
maxHitsPerQuery: 20,
indexes: ['products'],
validity: 0,
},
});
console.log(`Created rate-limited key: ${key}`);
Step 2: Implement Backoff for Sustained 429s
import { ApiError } from 'algoliasearch';
async function withBackoff<T>(
operation: () => Promise<T>,
config = { maxRetries: 5, baseDelayMs: 1000, maxDelayMs: 30000 }
): Promise<T> {
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
if (attempt === config.maxRetries) throw error;
if (error instanceof ApiError) {
if (error.status !== 429 && error.status < 500) throw error;
}
const delay = Math.min(
config.baseDelayMs * Math.pow(2, attempt) + Math.random() * 500,
config.maxDelayMs
);
.();
( (r, delay));
}
}
();
}
{ hits } = (
client.({ : , : { : } })
);
Step 3: Throttled Batch Indexing
import PQueue from 'p-queue';
const indexingQueue = new PQueue({
concurrency: 1,
interval: 1000,
intervalCap: 2,
});
async function throttledBulkIndex(records: Record<string, any>[]) {
const BATCH_SIZE = 500;
const chunks: Record<string, any>[][] = [];
for (let i = 0; i < records.length; i += BATCH_SIZE) {
chunks.push(records.slice(i, i + BATCH_SIZE));
}
let indexed = 0;
await Promise.all(
chunks.map(chunk =>
indexingQueue.add(async () => {
{ taskID } = client.({
: ,
: chunk,
});
client.({ : , taskID });
indexed += chunk.;
.();
})
)
);
}
Step 4: Monitor Usage Approaching Limits
async function checkKeyUsage(apiKey: string) {
const keyInfo = await client.getApiKey({ key: apiKey });
console.log({
description: keyInfo.description,
maxQueriesPerIPPerHour: keyInfo.maxQueriesPerIPPerHour,
acl: keyInfo.acl,
indexes: keyInfo.indexes,
});
}
async function checkRecordUsage() {
const { items } = await client.listIndices();
const totalRecords = items.reduce((sum, idx) => sum + (idx.entries || 0), 0);
console.log(`Total records across all indices: ${totalRecords.toLocaleString()}`);
}
Error Handling
| Scenario | Detection | Response |
|---|
| Burst spike (429) | ApiError with status 429 | Built-in retry handles it; add backoff for persistence |
| Sustained overload | Repeated 429s across minutes | Reduce batch size and frequency |
| Indexing queue full | 429 with "Too many jobs" | Pause indexing, wait for queue drain |
| Plan limit reached | 429 with quota message | Upgrade plan or reduce record count |
Resources
Next Steps
For security configuration, see algolia-security-basics.