CLAUDE LABJP
PRICING — September 1 was the scheduled date for the Sonnet 5 price increase, and it did not happen. The introductory $2/$10 per MTok now stands as the regular pricePARTNER — Salesforce and Anthropic announced Claudeforce, an expanded partnership. The Salesforce in Claude plugin ships with 37 prebuilt sales skills, from meeting prep to pipeline managementTRUST — Claudeforce serves Claude through Amazon Bedrock inside the Salesforce Trust Boundary, so data and inference never leave the security perimeter — an answer aimed squarely at regulated industriesBETA — Salesforce in Claude is with select pilot customers for now, with an open beta expected during SeptemberLIMITS — The 50% weekly-limit boost runs through September 13. From September 14 the permanent level is 25% above the pre-promotion baseline, roughly a 17% cut from todayRELEASE — Claude Code has shipped nothing since v2.1.251 on August 28. Against a pace of one release every 0.8 days, a four-day gap is among the longest yetPRICING — September 1 was the scheduled date for the Sonnet 5 price increase, and it did not happen. The introductory $2/$10 per MTok now stands as the regular pricePARTNER — Salesforce and Anthropic announced Claudeforce, an expanded partnership. The Salesforce in Claude plugin ships with 37 prebuilt sales skills, from meeting prep to pipeline managementTRUST — Claudeforce serves Claude through Amazon Bedrock inside the Salesforce Trust Boundary, so data and inference never leave the security perimeter — an answer aimed squarely at regulated industriesBETA — Salesforce in Claude is with select pilot customers for now, with an open beta expected during SeptemberLIMITS — The 50% weekly-limit boost runs through September 13. From September 14 the permanent level is 25% above the pre-promotion baseline, roughly a 17% cut from todayRELEASE — Claude Code has shipped nothing since v2.1.251 on August 28. Against a pace of one release every 0.8 days, a four-day gap is among the longest yet
Articles/API & SDK
API & SDK/2026-03-09Intermediate

Claude API Rate Limits — Designing Automation That Doesn't Stall on 429s

Understand how Claude API rate limits (RPM, TPM, TPD) work, and learn practical patterns — token optimization, request queuing, batch processing, and Retry-After-aware retries — drawn from running multiple sites on automation.

API28rate limits6token managementscalingoptimization4

Claude API Rate Limits — Designing Automation That Doesn't Stall

When you run several blogs on automated posting, you notice a strange thing: requests stall only in the moments when a batch goes out at night. Chase it down and the cause is almost never a bug in the code — it's rate limiting. If you're folding the Claude API into your own automation as an indie developer, the more you understand this behavior up front, the less you scramble later.

Here I walk through how RPM, TPM, and TPD work, how to save tokens, how to control request flow, and how to retry gracefully when you do hit a limit — in the order I picked them up while running things in production.

How Rate Limits Work

Rate limits ensure API stability and fair resource distribution across all users.

Types of Limits

Claude API applies rate limits on three axes:

Limit TypeDescriptionUnit
RPM (Requests Per Minute)Maximum requests per minuteRequest count
TPM (Tokens Per Minute)Maximum input + output tokens per minuteToken count
TPD (Tokens Per Day)Maximum input + output tokens per dayToken count

Plan-Based Limits

Rate limits vary by plan and model. Check Anthropic's documentation for the latest values. Higher-tier plans generally receive higher limits.

Using Response Headers

API responses include headers showing your current rate limit status. Use these to control request flow:

RateLimit-Limit-Requests: 50
RateLimit-Limit-Tokens: 90000
RateLimit-Remaining-Requests: 35
RateLimit-Remaining-Tokens: 72000
RateLimit-Reset-Requests: 2026-03-09T12:00:30Z
RateLimit-Reset-Tokens: 2026-03-09T12:00:30Z
Retry-After: 15

Optimizing Token Usage

Optimizing token consumption improves both cost efficiency and rate limit headroom.

1. Prompt Optimization

Write concise, effective prompts to reduce input tokens:

# Inefficient prompt (high token count)
inefficient_prompt = """
Please read the following text. Please analyze the content of the text.
Based on your analysis, please generate a summary of the text.
Please make the summary concise. Keep it as short as possible.
Avoid long summaries. Extract only the key points.
"""
 
# Optimized prompt (same intent, fewer tokens)
efficient_prompt = """
Summarize the following text in 3 sentences or fewer.
"""

2. Setting max_tokens Appropriately

Set max_tokens to the minimum needed for your use case:

import anthropic
 
client = anthropic.Anthropic()
 
# For short expected responses
response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=256,  # Use a small value for short responses
    messages=[
        {"role": "user", "content": "Translate this word to Japanese: efficiency"}
    ]
)

3. Efficient System Prompts

System prompts are sent with every request, so brevity matters:

# Verbose system prompt
verbose_system = """
You are an excellent assistant. Please answer user questions politely.
Answers should be accurate, easy to understand, and of appropriate length.
Include examples when needed. If uncertain, communicate that clearly.
Understand the user's intent precisely and provide optimal answers.
"""
 
# Optimized system prompt
concise_system = "Accurate, concise technical assistant. State uncertainty when present."

4. Pre-Checking Token Counts

Estimate token counts before sending requests to avoid rate limit overruns:

import anthropic
 
client = anthropic.Anthropic()
 
# Use the token counting API
count_response = client.messages.count_tokens(
    model="claude-sonnet-4-6",
    messages=[
        {"role": "user", "content": "A long text..."}
    ],
    system="System prompt"
)
 
print(f"Input tokens: {count_response.input_tokens}")

Request Efficiency Techniques

1. Request Queuing

Queue requests with flow control to prevent hitting rate limits:

import asyncio
import time
from collections import deque
 
class RequestQueue:
    """Rate-limit-aware request queue"""
 
    def __init__(self, max_rpm: int = 50, max_tpm: int = 90000):
        self.max_rpm = max_rpm
        self.max_tpm = max_tpm
        self.request_times: deque = deque()
        self.token_usage: deque = deque()
        self.lock = asyncio.Lock()
 
    async def wait_if_needed(self, estimated_tokens: int):
        """Wait if approaching rate limits"""
        async with self.lock:
            now = time.time()
 
            # Remove entries older than 1 minute
            while self.request_times and now - self.request_times[0] > 60:
                self.request_times.popleft()
            while self.token_usage and now - self.token_usage[0][0] > 60:
                self.token_usage.popleft()
 
            # RPM check
            if len(self.request_times) >= self.max_rpm:
                wait_time = 60 - (now - self.request_times[0])
                if wait_time > 0:
                    print(f"RPM limit approaching. Waiting {wait_time:.1f}s")
                    await asyncio.sleep(wait_time)
 
            # TPM check
            current_tokens = sum(t[1] for t in self.token_usage)
            if current_tokens + estimated_tokens > self.max_tpm:
                wait_time = 60 - (now - self.token_usage[0][0])
                if wait_time > 0:
                    print(f"TPM limit approaching. Waiting {wait_time:.1f}s")
                    await asyncio.sleep(wait_time)
 
            self.request_times.append(time.time())
            self.token_usage.append((time.time(), estimated_tokens))

2. Using Batch Processing

For high-volume workloads, the Message Batches API helps avoid rate limit pressure:

import anthropic
 
client = anthropic.Anthropic()
 
# Create a batch request
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"request-{i}",
            "params": {
                "model": "claude-sonnet-4-6",
                "max_tokens": 1024,
                "messages": [
                    {"role": "user", "content": f"Task {i}: {task}"}
                ]
            }
        }
        for i, task in enumerate(tasks)
    ]
)
 
# Check batch status
result = client.messages.batches.retrieve(batch.id)
print(f"Status: {result.processing_status}")

Key benefits of batch processing:

  • Rate limits are managed separately from real-time requests
  • 50% cost discount
  • Efficient handling of large request volumes
  • Results delivered within 24 hours

3. Leveraging Prompt Caching

Use caching for repeated prompts to reduce token reprocessing:

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "Large context content...",
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[
        {"role": "user", "content": "Your question"}
    ]
)

Cache hits reduce input token costs by 90%.

When You Hit a Limit — Don't Ignore Retry-After

No matter how well you smooth the flow, on a shared platform the chance of hitting a limit never quite reaches zero. I once found my auto-posting script stalled on a 429 in the middle of the night and only noticed the next morning. What that taught me: rather than trying to avoid the error, it's sturdier to design what happens after you receive a 429.

When the Claude API returns a 429, it often tells you how long to wait via the Retry-After header. Honoring that value beats guessing a delay yourself. Only when it's absent should you back off exponentially — and add a little jitter so retries from multiple processes don't collide on the same instant.

import time, random
import anthropic
from anthropic import RateLimitError
 
client = anthropic.Anthropic()
 
def create_resilient(messages, max_retries=6):
    """Honor Retry-After on 429; otherwise back off with jitter."""
    backoff = 2.0
    for attempt in range(max_retries):
        try:
            return client.messages.create(
                model="claude-sonnet-4-6",
                max_tokens=1024,
                messages=messages,
            )
        except RateLimitError as e:
            if attempt == max_retries - 1:
                raise
            retry_after = None
            resp = getattr(e, "response", None)
            if resp is not None:
                hdr = resp.headers.get("retry-after")
                if hdr:
                    retry_after = float(hdr)
            wait = retry_after if retry_after is not None else backoff
            wait += random.uniform(0, 0.5)  # jitter spreads out concurrent retries
            time.sleep(wait)
            backoff *= 2
    raise RuntimeError("max retries exceeded")

The priority that matters here: follow the server when it tells you how long to wait, and decide for yourself only when it doesn't. A fixed delay falls short during congestion and wastes time when things are quiet. Since I moved Dolice's automation to this shape, the nightly jobs almost never die on an error.

Monitoring and Visibility

Usage Tracking

import anthropic
from datetime import datetime
 
class UsageTracker:
    """Track API usage metrics"""
 
    def __init__(self):
        self.requests = []
 
    def track(self, response):
        """Record usage from a response"""
        self.requests.append({
            "timestamp": datetime.now().isoformat(),
            "model": response.model,
            "input_tokens": response.usage.input_tokens,
            "output_tokens": response.usage.output_tokens,
            "cache_read_tokens": getattr(
                response.usage, "cache_read_input_tokens", 0
            ),
            "cache_creation_tokens": getattr(
                response.usage, "cache_creation_input_tokens", 0
            ),
        })
 
    def summary(self):
        """Print usage summary"""
        total_input = sum(r["input_tokens"] for r in self.requests)
        total_output = sum(r["output_tokens"] for r in self.requests)
        total_cache = sum(r["cache_read_tokens"] for r in self.requests)
 
        print(f"Total requests: {len(self.requests)}")
        print(f"Total input tokens: {total_input:,}")
        print(f"Total output tokens: {total_output:,}")
        print(f"Cache read tokens: {total_cache:,}")
 
# Usage
tracker = UsageTracker()
response = client.messages.create(...)
tracker.track(response)
tracker.summary()

Scaling Strategies

Gradual Scale-Up

For production deployments, increase traffic gradually:

  1. Development: Default rate limits are sufficient
  2. Testing: Consider plan upgrades if load tests hit limits
  3. Early production: Monitor real traffic and adjust
  4. Scale phase: Contact Anthropic for custom rate limits

Requesting Higher Limits

If default limits are insufficient, request increases through the Anthropic Console. Prepare the following information:

  • Current usage patterns (actual RPM, TPM values)
  • Required limits with justification
  • Use case description
  • Expected traffic growth rate

Where to Start

Rate limits look like an obstacle, but they're really traffic control that keeps a shared resource fair. Before reaching for a higher plan, there's something you can do first.

The step I'd recommend: add one piece of usage logging to the code you already run. Just recording each response's usage reveals whether your bottleneck is input tokens or request frequency. Once you know which axis is jammed, the fix picks itself — trim prompts, throttle with a queue, or move to batches. Measure, then move. It looks like a detour, but it's the fastest road I've found.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

API & SDK2026-03-24
Claude API Usage & Cost API: Programmatic Cost Monitoring and Optimization
Learn how to use Anthropic's Usage & Cost Admin API to programmatically monitor, analyze, and optimize your Claude API spending with practical code examples.
API & SDK2026-07-24
When Memory Store Listings Returned Half the Rows: Migrating to agent-memory-2026-07-22
agent-memory-2026-07-22 changed memories.list: fixed ordering, stricter depth, segment-based path_prefix matching. How an audit quietly halved, an access layer that survives it, and measured depth=1 traversal cost.
API & SDK2026-07-14
A Two-Stage Pre-Publish Gate for User-Facing AI Text in Consumer Apps
Design a two-stage pre-publish gate for short AI-generated text you ship to end users: a deterministic rule layer plus a Claude classifier, with fail-closed handling, generation-time vetting, and a cost model. Full implementation code included.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →