Error-Resilient Claude API Clients in TypeScript with Retry Logic
Tired of Claude API calls failing due to rate limits or network glitches? Build a production-ready TypeScript client with smart retry logic to ensure rock-solid reliability.
Why Error-Resilient Clients Matter for Claude API
When integrating the Claude API into production apps, naive HTTP requests can lead to cascading failures. Rate limits (HTTP 429), timeouts, network hiccups, and partial responses disrupt user experience and waste developer time. This guide shows you how to create a battle-tested TypeScript wrapper around the Anthropic SDK, implementing exponential backoff, jitter, and intelligent error classification for seamless resilience.
We'll cover:
- Common Claude API failure modes
- Retry strategies tailored to Anthropic's rate limits
- A complete, copy-paste-ready client implementation
- Real-world testing and monitoring tips
Common Failure Modes in Claude API Calls
Claude's API is robust but not infallible. Here's what you'll encounter:
- Rate Limits (429): Tier-based limits on requests per minute (RPM) and tokens per minute (TPM). Exceeding triggers backoff headers like
retry-after. - Timeouts (408/ETIMEDOUT): Long prompts or high-load responses time out.
- Network Errors: DNS failures, connection resets, or proxy issues.
- Server Errors (5xx): Rare, but Anthropic's infra can hiccup.
- Partial Failures: Streaming responses cut short or invalid JSON.
The official @anthropic-ai/sdk handles basics but lacks built-in retries. Time to level up.
Core Principles of Retry Logic
Effective retries follow these rules:
- Categorize Errors: Retry on transient issues (429, 5xx, network); fail-fast on client errors (4xx).
- Exponential Backoff: Delay = min(base * 2^attempt, maxDelay).
- Jitter: Add randomness to prevent thundering herds: delay += random(0, delay).
- Max Retries: Cap at 5-10 to avoid infinite loops.
- Respect Headers: Honor
retry-afterfrom 429 responses.
For Claude, prioritize TPM over RPM—token-heavy messages burn limits fast.
Building the Resilient Client
We'll extend the Anthropic SDK with a ResilientClaudeClient class. Install dependencies:
npm install @anthropic-ai/sdk
npm install --save-dev @types/node
Step 1: Error Classification Utility
First, a function to classify retryable errors:
import { Anthropic } from '@anthropic-ai/sdk';
import { AxiosError } from 'axios'; // SDK uses axios internally
type ClaudeError = Anthropic.AnthropicError | AxiosError | Error;
type RetryDecision = 'retry' | 'abort' | number; // number for custom delay
function shouldRetry(error: ClaudeError, attempt: number): RetryDecision {
if (attempt >= 5) return 'abort'; // Max 5 retries
const status = 'status' in error ? (error as AxiosError).response?.status : undefined;
const message = error.message.toLowerCase();
// Retry on rate limits
if (status === 429 || message.includes('rate limit')) {
const retryAfter = (error as any).response?.headers['retry-after'];
return retryAfter ? parseInt(retryAfter, 10) * 1000 : 'retry';
}
// Retry on server errors and network issues
if (status && status >= 500) return 'retry';
if (message.includes('timeout') || message.includes('network') || message.includes('enonet')) return 'retry';
// Abort on client errors
if (status && status >= 400 && status < 500) return 'abort';
return 'abort';
}
Step 2: Retry Wrapper with Backoff
Core retry logic using promises:
function withRetry<T>(fn: () => Promise<T>, attempt = 0): Promise<T> {
return fn().catch(async (error: ClaudeError) => {
const decision = shouldRetry(error, attempt);
if (decision === 'abort') throw error;
const delay = typeof decision === 'number' ? decision : Math.min(100 * Math.pow(2, attempt), 30000) + Math.random() * 1000; // Expo + jitter
await new Promise(resolve => setTimeout(resolve, delay));
return withRetry(fn, attempt + 1);
});
}
Step 3: The Full Resilient Client
Wrap the SDK:
export class ResilientClaudeClient {
private client: Anthropic;
constructor(apiKey: string, options?: Anthropic.AnthropicInit) {
this.client = new Anthropic({
apiKey,
...options,
// Custom axios config for base timeout
timeout: 60000,
});
}
async messages(params: Anthropic.AnthropicMessageParamsNonStreaming, maxRetries = 5): Promise<Anthropic.AnthropicMessage> {
return withRetry(() => this.client.messages.create(params), 0);
}
async messagesStream(params: Anthropic.AnthropicMessageParams): Promise<Anthropic.AnthropicStream> {
return withRetry(() => this.client.messages.stream(params), 0);
}
// Token estimator for preemptive rate limit checks
estimateTokens(prompt: string): number {
// Rough heuristic: 4 chars/token
return Math.ceil(prompt.length / 4) + 100; // + overhead
}
}
Usage Examples
Non-Streaming Messages
const client = new ResilientClaudeClient('your-api-key');
const response = await client.messages({
model: 'claude-3-5-sonnet-20240620',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Explain quantum computing simply.' }],
});
console.log(response.content[0].text);
Retries automatically on 429s with backoff.
Streaming with Resilience
For real-time apps:
const stream = await client.messagesStream({
model: 'claude-3-opus-20240229',
messages: [{ role: 'user', content: 'Write a blog post...' }],
stream: true,
});
for await (const chunk of stream) {
console.log(chunk.type === 'content_block_delta' ? chunk.delta.text : '');
}
Streams resume on transient failures.
Advanced: Rate Limit Awareness
Pre-check tokens:
const prompt = 'Long user input...';
if (client.estimateTokens(prompt) > 100000) {
console.warn('High token count—consider truncation');
}
Testing Your Client
Mock errors with nock or SDK mocks:
import nock from 'nock';
nock('https://api.anthropic.com')
.post('/v1/messages')
.reply(429, {}, { 'retry-after': '1' });
// Test retry triggers
Run load tests with Artillery or k6 to simulate rate limits.
Monitoring and Logging
Integrate with Sentry or console:
import * as Sentry from '@sentry/node';
// In shouldRetry:
Sentry.captureException(error, { tags: { attempt, decision } });
Track metrics: retry count, success rate, avg delay.
Best Practices for Production
- Tier Awareness: Check your Anthropic tier; adjust maxRetries accordingly.
- Circuit Breaker: Use libraries like
opossumfor global outages. - Queueing: For high-volume, enqueue requests with BullMQ.
- Idempotency: Add
anthropic-versionand client IDs. - Multi-Region: Fallback to secondary API endpoints if available.
| Scenario | Recommended Max Retries | Base Delay |
|---|---|---|
| Dev | 3 | 100ms |
| Prod | 8 | 250ms |
| High-TPM | 5 | 500ms |
Conclusion
This resilient client turns flaky Claude integrations into reliable powerhouses. Copy the code, tweak for your stack, and deploy confidently. Got questions? Share in the comments or on claudedirectory.com forums.
Word count: ~1450
Comments
More Blog
View allBuilding Voice Agents with Claude API and ElevenLabs: Conversational AI Guide
Build natural voice agents combining Claude API's superior reasoning with ElevenLabs' lifelike TTS. This end-to-end guide creates a conversational web app with STT, AI chat, and speech synthesis.
Claude vs Mistral Large 2: 2025 Data Analysis Benchmarks and Use Cases
As data volumes explode in 2025, choosing between Claude's reasoning depth and Mistral Large 2's efficiency is critical. We benchmark SQL generation, visualizations, and large datasets to reveal the w
Claude Enterprise for Cybersecurity: Threat Modeling and Incident Response
In the high-stakes world of cybersecurity, rapid threat modeling and incident response can mean the difference between containment and catastrophe. Discover how Claude Enterprise empowers security tea
Claude Code in VS Code: Custom Commands for Refactoring Large Codebases
Refactoring sprawling codebases manually? Harness Claude Code's power in VS Code with custom commands to automate AI-driven refactors across TypeScript and Python projects—saving hours of drudgery.
Claude SDK Rust for Blockchain: Smart Contract Auditing Agents
Build blazing-fast smart contract auditing agents in Rust using the Claude SDK. Harness Claude's reasoning to scan Solidity code for vulnerabilities like reentrancy and overflows.
Advanced Claude Artifacts: Collaborative Editing in Multi-User Sessions
Elevate team productivity with Claude Artifacts in multi-user projects—enable real-time iterative editing for code reviews and docs without leaving the interface.