API Rate Limit Error and Waiting Time for Batch Deletion
I can see from your error message that the response headers contain the exact information you need! The key headers are:
'retry-after': '1'- This tells you to wait 1 second before retrying'x-ratelimit-remaining-second': '0'- You've exhausted your current second's quota
So the immediate answer is: wait 1 second (as indicated by the retry-after header) before making your next request.
However, for batch deletions, you're hitting rate limits because you're likely making too many individual requests. Here are much more efficient approaches:
1. Use transactions with multiple mutations (most efficient)
Instead of one mutation per request, batch multiple mutations into a single transaction. You can include many delete operations in one request:
const mutations = documents.map(doc => ({ delete: { id: doc._id } }));
// Batch them into chunks
const chunkSize = 100;
for (let i = 0; i < mutations.length; i += chunkSize) {
const chunk = mutations.slice(i, i + chunkSize);
await client.mutate(chunk);
// Add a small delay between batches if needed
await new Promise(resolve => setTimeout(resolve, 50));
}2. Use the Sanity CLI migration tool
The Sanity CLI migration tooling has built-in abstractions that automatically handle batching and rate limits. This is the recommended approach for bulk operations:
# For deleting all documents of a type
sanity documents delete '*[_type == "student"]'
# Or for a complete fresh start
sanity dataset delete <dataset-name>
sanity dataset create <dataset-name>The CLI migration tool provides automatic batching of mutations into transactions to avoid rate limits, which is exactly what you need for this scenario.
3. Implement retry logic with exponential backoff
When you do hit rate limits, implement a retry strategy that respects the retry-after header:
async function mutateWithRetry(mutations, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.mutate(mutations);
} catch (error) {
if (error.statusCode === 429) {
const retryAfter = parseInt(error.response.headers['retry-after'] || '1', 10);
console.log(`Rate limited. Waiting ${retryAfter}s before retry...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
} else {
throw error;
}
}
}
throw new Error('Max retries exceeded');
}By batching mutations properly (100+ deletes per request) instead of making individual mutation calls, you can delete thousands of documents efficiently without hitting rate limits. The key is reducing the number of HTTP requests by grouping multiple operations into single transactions.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.