← LearnClaude API · Operations

Claude API Retry Logic: Best Practices That Actually Work

The best practices for Claude API retry logic are: always read the retry-after header from 429 responses before sleeping, use exponential backoff with jitter for multi-worker systems, and wrap your entire streaming response in error handling—not just the connection phase.

The best practices for Claude API retry logic are: always read the retry-after header from 429 responses before sleeping, use exponential backoff with jitter for multi-worker systems, and wrap your entire streaming response in error handling—not just the connection phase. Getting these three things right is the difference between an application that recovers gracefully under load and one that cascades into a retry storm.

What Error Codes Do You Need to Handle in Claude API Retry Logic?

The Claude API surfaces several error codes that warrant retry logic. Understanding each one helps you write targeted handlers rather than catching everything blindly.

  • 429 (rate limit exceeded): Returned when your organization exceeds its Requests Per Minute (RPM), Input Tokens Per Minute (ITPM), or Output Tokens Per Minute (OTPM) ceiling. The response includes a machine-readable JSON body identifying which limit was breached, plus a retry-after header specifying how many seconds to wait.
  • 529 (overloaded): Indicates the API is under heavy load. Treat this as a transient error and apply the same backoff logic as a 429.
  • 500 (api_error): A server-side error. Retrying after a short delay is usually appropriate.
  • 504 (timeout_error): The request timed out. Retry with backoff, and consider whether your request can be broken into smaller chunks.

For a complete reference on error shapes and codes, see the Errors – Claude API Documentation.

How Do You Implement Basic 429 Retry Logic in Python?

The simplest correct implementation reads the retry-after header and sleeps for exactly that duration. Rapid-fire retries without honoring this header will simply continue to receive 429 errors and may make the situation worse.

import anthropic
import time

client = anthropic.Anthropic(api_key="YOUR_KEY")

def call_with_retry(prompt, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.messages.create(
                model="claude-sonnet-4-5-20250929",
                max_tokens=256,
                messages=[{"role": "user", "content": prompt}]
            )
        except anthropic.APIStatusError as e:
            if e.status_code == 429:
                wait = int(e.response.headers.get("retry-after", 60))
                print(f"Rate limited. Sleeping {wait}s (attempt {attempt+1})")
                time.sleep(wait)
            else:
                raise
    raise RuntimeError("Max retries exceeded")

print(call_with_retry("What is 2+2?").content[0].text)

Key points in this pattern:

  1. Catch anthropic.APIStatusError and check the status code before deciding to sleep.
  2. Read the retry-after header; default to a safe fallback if the header is absent.
  3. Re-raise any non-retryable error so it is never silently swallowed.

How Do You Add Exponential Backoff with Jitter for Production Systems?

When multiple worker threads or processes share the same organizational rate limit pool, naive fixed-wait retries cause synchronized retry storms—every worker wakes up at the same moment and hammers the API together. Exponential backoff with added randomness (jitter) spreads retries out over time.

The Claude API rate limits documentation notes that limits are applied at the organization level, which means all your workers compete for the same quota. Jitter is not optional in multi-worker deployments—it is essential.

import anthropic
from tenacity import (
    retry, wait_exponential, wait_random, retry_if_exception,
    stop_after_attempt, before_sleep_log
)
import logging

logger = logging.getLogger(__name__)
client = anthropic.Anthropic(api_key="YOUR_KEY")

def is_retryable(exc):
    return (
        isinstance(exc, anthropic.APIStatusError)
        and exc.status_code in (429, 500, 529)
    )

@retry(
    retry=retry_if_exception(is_retryable),
    wait=wait_exponential(multiplier=1, min=4, max=60) + wait_random(0, 2),
    stop=stop_after_attempt(6),
    before_sleep=before_sleep_log(logger, logging.WARNING)
)
def safe_create(prompt):
    return client.messages.create(
        model="claude-sonnet-4-5-20250929",
        max_tokens=512,
        messages=[{"role": "user", "content": prompt}]
    )

result = safe_create("Summarize the token bucket algorithm in two sentences.")
print(result.content[0].text)

This pattern logs each retry attempt at WARNING level, which lets you monitor retry rates in production dashboards and catch situations where a service is consistently hitting its ceiling.

What Are the Most Common Pitfalls in Claude API Retry Logic?

Retrying immediately without reading the retry-after header

Rapid-fire retries after a 429 will simply continue to receive 429 errors. Always parse the retry-after header value and sleep for exactly that many seconds before retrying.

Assuming streaming errors only happen at connection time

When using Server-Sent Events (SSE) streaming, the API can return an error after delivering an initial 200 OK. Your error handling must wrap the entire stream iteration—not just the initial connection—in a try/except block.

Ramping traffic too sharply

Sharp acceleration from near-zero to full-speed can trigger acceleration limits even if you are well below your steady-state RPM ceiling. Ramp request volume gradually. If you anticipate a large traffic spike, contact Anthropic sales in advance.

Over-counting ITPM when prompt caching is active

On most Claude models, only uncached input tokens count toward the ITPM limit. If you are tracking your own ITPM consumption, subtract cache-read tokens from your total input tokens to avoid throttling yourself unnecessarily.

Missing the pause_turn stop reason in agent loops

In agentic workflows, always check the stop reason after each API call. If it is pause_turn, append the partial assistant turn and any tool results to the messages array and resubmit—otherwise the task silently stops mid-execution.

When Should You Use the Message Batches API Instead of Retry Logic?

Retry logic is the right tool when you need real-time, synchronous responses and can tolerate occasional delays. But for high-volume workloads where latency tolerance is high, the Message Batches API is a better fit: it operates on separate rate limit pools and is priced at a significant discount compared to the standard Messages API. A legal tech company processing thousands of contracts per day, for example, can combine the Batches API with exponential backoff on transient errors to saturate throughput without manual intervention.

How Do You View and Manage Your Rate Limits in the Console?

  1. Log in to the Claude Console at console.anthropic.com.
  2. Navigate to Settings > Limits to view your organization's current tier and its associated RPM, ITPM, and OTPM ceilings.
  3. Navigate to the Usage page to see real-time rate limit charts showing headroom, peak usage periods, and caching rates.
  4. To set workspace-level sub-limits, open the Console workspace settings and configure per-workspace caps below your organization maximum.
  5. To query limits programmatically, provision an Admin API key in the Console, then call the rate limits endpoint.
  6. To raise limits beyond your current tier, contact Anthropic sales for custom limits or Priority Tier access.

Understanding your actual limits before writing production code prevents surprise 429 errors and helps you plan batching or caching strategies early.

Is Prompt Caching Worth It for Throughput?

Yes—prompt caching is one of the most effective ways to increase usable throughput without upgrading your tier. Because only uncached input tokens count toward the ITPM limit on most models, caching a large shared system prompt means only the small per-request delta counts against your limit. An AI writing tool that prepends a large shared system prompt to every request can effectively multiply its usable throughput this way, with no tier upgrade required.

How Do Multiple Workspaces Help with Rate Limit Isolation?

For multi-tenant SaaS platforms, creating one Console workspace per client and assigning each a workspace-level rate limit prevents one noisy tenant from exhausting shared organizational quota. This also gives per-tenant usage visibility without requiring separate Anthropic accounts—a clean architectural pattern for platforms serving multiple enterprise clients.

Key insight: Rate limits are also enforced per model. Distributing requests across multiple models—routing simpler tasks to a faster, lighter model and complex ones to a more capable one—lets you use separate rate limit pools simultaneously, increasing aggregate throughput without any tier change.

What Is the Token Bucket Algorithm and Why Does It Matter for Retry Timing?

The Claude API uses a token bucket algorithm, meaning capacity refills continuously rather than resetting at fixed clock intervals. This has a practical implication for retry timing: you do not need to wait until the top of the next minute. If you hit your RPM ceiling, capacity begins refilling immediately. Honoring the retry-after header gives you the precise wait time the server calculates based on this continuous refill—which is why reading it is always more accurate than guessing a fixed sleep duration.

Frequently asked questions

What HTTP status code does the Claude API return when you exceed a rate limit?

The Claude API returns an HTTP 429 error when any rate limit is exceeded. The response includes a machine-readable JSON body identifying which limit was breached and a retry-after header specifying how many seconds to wait before retrying.

Should I use the same retry logic for streaming responses as for standard requests?

No. For streaming responses delivered over SSE, errors can surface after an initial 200 OK. You must wrap the entire stream iteration—not just the connection phase—in a try/except block to catch these late-arriving errors.

Does prompt caching help with rate limits?

Yes. On most Claude models, only uncached input tokens count toward the ITPM limit. Caching a large shared system prompt means only the small per-request delta counts against your limit, effectively multiplying usable throughput.

What is the difference between a 429 and a 529 error from the Claude API?

A 429 means your organization has exceeded a configured rate limit (RPM, ITPM, or OTPM). A 529 means the API is overloaded. Both are transient and should be handled with backoff and retry logic.

How do I increase my Claude API rate limits?

Organizations advance through usage tiers automatically as cumulative spend increases, unlocking higher RPM, ITPM, and OTPM ceilings at each level. For limits beyond Tier 4, you can contact Anthropic sales for custom limits or Priority Tier access.

Why is exponential backoff with jitter better than a fixed wait time?

When multiple workers share the same organizational rate limit pool, fixed-wait retries cause synchronized retry storms—every worker retries at the same moment. Adding jitter (randomness) spreads retries out over time, reducing the chance of all workers colliding again.

Go deeper

Rate limits & error handling is one of 85 features in Claude Master — the independent, continuously updated manual with worked examples, the pitfalls, and the workflows that put Claude to work.

Get Claude Master — founding price →

Independent product. Not affiliated with or endorsed by Anthropic. "Claude" is a trademark of Anthropic, used here only to describe the subject of this guide.