Our Node.js service occasionally hits 429 Too Many Requests status codes during high concurrency spikes when sending requests to the Anthropic Claude API. While the SDK handles basic retries, some burst spikes still fail standard calls.
How does Anthropic communicate rate limit details?
When an API call receives a 429 status code, the response headers contain specific timing instructions:
retry-after-ms: The recommended waiting duration in milliseconds before retrying.anthropic-ratelimit-requests-reset: Timestamp indicating when the current window request allowance resets.
Implementing custom backoff logic
If you need custom retry handling outside of standard client parameters, you can intercept 429 exceptions and read the header hints directly.
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
async function sendPromptWithRetry(params, retries = 3) {
try {
// Execute Claude message request
return await anthropic.messages.create(params);
} catch (error) {
// Check if error is due to HTTP 429 rate limiting
if (error.status === 429 && retries > 0) {
// Read recommended backoff time from response headers or fallback to 2 seconds
const waitMs = parseInt(error.headers?.['retry-after-ms']) || 2000;
console.warn(`Rate limit encountered. Retrying in ${waitMs}ms...`);
// Pause execution for header-specified delay
await new Promise(resolve => setTimeout(resolve, waitMs));
// Re-attempt request with decremented retry budget
return sendPromptWithRetry(params, retries - 1);
}
throw error;
}
}What strategies do developers use to coordinate concurrency across distributed queue workers to prevent 429 spikes altogether?