Diagnóstico de Erros de Limite de Taxa 429 e Esgotamento de Cota Sob Carga
Um 429 da API Claude sempre significa a mesma coisa no nível do protocolo: você excedeu um limite. No entanto, o limite específico, o motivo e a correção são diferentes a cada vez. Diagnosticar um 429 corretamente, antes de mexer na sua lógica de retentativa, é o que separa uma correção de cinco minutos de um incidente recorrente.
Resumo
A API Claude impõe vários limites de taxa independentes simultaneamente: requisições por minuto, tokens de entrada por minuto e tokens de saída por minuto, cada um rastreado separadamente por modelo.
Uma resposta 429 informa que um limite foi atingido, mas os cabeçalhos da resposta indicam qual deles, e esse detalhe muda o que você deve realmente fazer a respeito.
Os limites de taxa também vêm em dois sabores que parecem idênticos do ponto de vista do cliente, mas exigem correções diferentes: um teto de cota genuíno da conta ou organização e um breve pico de tráfego concorrente que excede momentaneamente sua taxa de transferência alocada.
Esta página detalha a leitura do sinal que a API fornece, a distinção entre picos breves e sobrecarga sustentada, e a construção do registro de diagnóstico mínimo que torna a próxima tempestade de 429 uma leitura rápida em vez de um jogo de adivinhação.
Ela para no diagnóstico. Assim que você souber qual limite está atingindo e qual é o formato do tráfego, o artigo sobre retentativa e backoff cobrirá o que construir em resposta.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
import anthropic
client = anthropic.Anthropic()
try:
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Resuma este relatório."}],
)
except anthropic.RateLimitError as e:
headers = e.response.headers
print("retry-after:", headers.get("retry-after"))
print("requests remaining:", headers.get("anthropic-ratelimit-requests-remaining"))
print("input tokens remaining:", headers.get("anthropic-ratelimit-input-tokens-remaining"))
print("output tokens remaining:", headers.get("anthropic-ratelimit-output-tokens-remaining"))Quando usar isso:
- Seu aplicativo está retornando 429s intermitentemente e você precisa saber se é um limite de contagem de requisições, tokens de entrada ou tokens de saída antes de escolher uma correção.
- Você suspeita que um pico de requisições concorrentes, em vez de volume sustentado, está acionando o limite.
- Você está definindo uma linha de base antes de adicionar lógica de retentativa e backoff, para que possa medir se a correção realmente funcionou.
- Você precisa distinguir entre "ficamos sem cota para o período de faturamento" e "excedemos momentaneamente nossa alocação por minuto".
Exemplo de Trabalho
import logging
import time
import anthropic
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("rate_limit_diagnostics")
client = anthropic.Anthropic()
def diagnose_rate_limit(exc: anthropic.RateLimitError) -> dict:
"""Extrai uma assinatura estruturada de um RateLimitError para que possa ser
registrada, agregada e comparada entre incidentes."""
headers = exc.response.headers
requests_remaining = headers.get("anthropic-ratelimit-requests-remaining")
input_tokens_remaining = headers.get("anthropic-ratelimit-input-tokens-remaining")
output_tokens_remaining = headers.get("anthropic-ratelimit-output-tokens-remaining")
retry_after = headers.get("retry-after")
if requests_remaining == "0":
limit_type = "requests_per_minute"
elif input_tokens_remaining == "0":
limit_type = "input_tokens_per_minute"
elif output_tokens_remaining == "0":
limit_type = "output_tokens_per_minute"
else:
limit_type = "unknown_or_org_quota"
signature = {
"limit_type": limit_type,
"retry_after_seconds": retry_after,
"request_id": exc.request_id,
"timestamp": time.time(),
}
logger.warning("claude.rate_limited", extra=signature)
return signature
def call_with_diagnostics(prompt: str) -> anthropic.types.Message | None:
try:
return client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
except anthropic.RateLimitError as e:
diagnose_rate_limit(e)
return None
if __name__ == "__main__":
call_with_diagnostics("Elabore uma atualização de status para o canal de incidentes.")O que isso demonstra:
- Leitura dos cabeçalhos
anthropic-ratelimit-*para determinar qual limite específico (requisições, tokens de entrada ou tokens de saída) causou o 429, em vez de tratar cada 429 da mesma forma. - Captura de
retry-afterpara saber quanto tempo a própria API recomenda esperar antes de tentar novamente. - Registro de uma assinatura estruturada por evento, para que um pico de 429s produza um conjunto de dados agregável em vez de uma parede de rastros de pilha idênticos.
- Manter o
request_idpara correlação com o suporte da Anthropic ou sua própria Análise de Causa Raiz (RCA) se o padrão se repetir.
Mergulho Profundo
Como Funciona
- A API Claude rastreia limites de taxa por organização e por modelo, em três dimensões independentes: requisições por minuto, tokens de entrada por minuto e tokens de saída por minuto.
- Uma requisição pode ser rejeitada por exceder qualquer um desses limites, mesmo que os outros dois tenham margem, então uma única linha de log "rate limited" sem o detalhe do cabeçalho informa quase nada.
- O cabeçalho
retry-afteré a recomendação da própria API sobre quanto tempo esperar, expressa em segundos, e leva em conta o limite específico que foi excedido. - Tetos de cota (um limite rígido vinculado ao seu nível de conta ou limite de gastos) parecem idênticos a um limite transitório por minuto no tipo de exceção, mas não se resolvem sozinhos como um limite por minuto, exigindo um upgrade de nível ou uma conversa de suporte.
Assinaturas de Limite de Taxa em Resumo
| Cabeçalho | Significado | O Que Isso Diz a Você |
|---|---|---|
anthropic-ratelimit-requests-remaining | Requisições restantes na janela atual | 0 significa que você está atingindo o teto de contagem de requisições |
anthropic-ratelimit-input-tokens-remaining | Tokens de entrada restantes na janela atual | 0 significa que prompts longos ou contexto são o motor |
anthropic-ratelimit-output-tokens-remaining | Tokens de saída restantes na janela atual | 0 significa que max_tokens altos ou gerações longas são o motor |
retry-after | Segundos até que a API espere que você tente novamente | Um valor curto (abaixo de alguns segundos) geralmente significa um pico; um valor longo frequentemente significa sobrecarga sustentada |
Tráfego Disperso vs. Sustentado
- Disperso: um pico curto, muitas vezes causado por um job em lote, uma tempestade de retentativas ou muitos usuários acionando uma ação simultaneamente (por exemplo, um deploy que redefine caches do lado do cliente e causa uma "thundering herd" de requisições). A assinatura é um cluster de 429s em uma janela de tempo estreita, seguido por uma recuperação limpa.
- Sustentado: seu tráfego estável cresceu além do que seu nível atual ou concorrência configurada suporta. A assinatura é uma taxa de 429 que não se recupera totalmente entre as janelas; ela degrada, recupera parcialmente e depois degrada novamente.
- Plote ocorrências de 429 em uma janela deslizante de 5 minutos antes de decidir qual delas você está observando. Um único gráfico de pico não é suficiente para distinguir entre disperso e sustentado; você precisa ver se a linha de base em si está subindo.
# Uma maneira mínima de distinguir entre disperso e sustentado: rastrear a proporção
# de chamadas com limite de taxa em relação ao total de chamadas em uma janela deslizante e observar
# se a linha de base se recupera entre os picos.
from collections import deque
import time
class RateLimitTracker:
def __init__(self, window_seconds: int = 300):
self.window_seconds = window_seconds
self.events: deque[tuple[float, bool]] = deque()
def record(self, was_rate_limited: bool) -> None:
now = time.time()
self.events.append((now, was_rate_limited))
cutoff = now - self.window_seconds
while self.events and self.events[0][0] < cutoff:
self.events.popleft()
def rate_limited_ratio(self) -> float:
if not self.events:
return 0.0
limited = sum(1 for _, hit in self.events if hit)
return limited / len(self.events)Tetos de Cota vs. Limites por Minuto
| Sinal | Limite por Minuto | Teto de Cota da Conta/Organização |
|---|---|---|
| Recuperação | Limpa dentro da janela (tipicamente 60 segundos) | Não limpa até o período de faturamento ser redefinido ou o nível mudar |
retry-after | Geralmente segundos | Pode estar ausente ou não ser significativamente útil |
| Correção | Backoff, controle de concorrência, agrupamento de requisições | Solicitar um aumento de nível, revisar gastos, adicionar capacidade no console |
Armadilhas
-
Tratar cada 429 como o mesmo problema. Registrar "rate limited" sem a análise detalhada dos cabeçalhos oculta se é um limite de contagem de requisições, tokens de entrada ou tokens de saída. Correção: sempre registre os três cabeçalhos
anthropic-ratelimit-*-remainingjuntamente com a exceção. -
Confundir um pico com sobrecarga sustentada. Um único alerta disparando durante um pico de cinco minutos pode acionar um upgrade de capacidade que não resolve um padrão de pico recorrente. Correção: rastreie a proporção deslizante por pelo menos 15-30 minutos antes de concluir que é sustentado.
-
Ignorar
retry-after. Criar seu próprio intervalo de backoff fixo quando a API já informa quanto tempo esperar desperdiça retentativas e pode piorar o limite. Correção: leia e respeiteretry-afterquando presente; trate-o como um piso, não um teto. -
Não separar limites por modelo. Se seu tráfego chama tanto Sonnet quanto Haiku, um 429 no limite de um modelo não significa que o outro modelo também está restrito. Correção: marque os logs de diagnóstico com o parâmetro
modelusado na requisição que falhou. -
Diagnosticar apenas com logs do lado do cliente. O tempo do lado do cliente pode fazer com que uma resposta lenta e saudável pareça idêntica a uma retentativa em fila após um 429. Correção: sempre capture a exceção real e seus cabeçalhos, não apenas o tempo de requisição decorrido.
-
Assumir que o esgotamento da cota se autoconsertará como um limite por minuto. Esperar e retentar contra uma cota de conta genuína apenas produz mais 429s. Correção: verifique se
retry-afterestá presente e é curto antes de assumir que isso é transitório; se estiver ausente ou for incomumente longo, verifique o status da cota da sua conta no console.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Inspeção manual de cabeçalhos (este artigo) | Você precisa entender a causa exata antes de alterar o comportamento | Você já sabe a causa e só precisa de resiliência, use o artigo de retentativa/backoff em vez disso |
| Um painel dedicado de limite de taxa/pipeline de métricas | Você tem incidentes recorrentes de 429 e precisa de dados de tendências históricas | Você está diagnosticando um pico pela primeira vez ou pontual, um painel é excessivo para um único incidente |
| Solicitar um aumento de cota/nível | O diagnóstico confirma sobrecarga sustentada contra um teto de cota real | O padrão é disperso, um teto mais alto apenas adia o mesmo problema |
FAQs
Qual é a diferença entre um limite de taxa e uma cota?
- Um limite de taxa é um teto rotativo por minuto em requisições, tokens de entrada ou tokens de saída, rastreado por modelo.
- Uma cota é tipicamente um limite em nível de conta ou organização vinculado ao seu nível de uso ou limite de gastos, e não é redefinida a cada minuto.
Como sei qual limite específico causou um determinado 429?
Verifique os cabeçalhos de resposta anthropic-ratelimit-requests-remaining, anthropic-ratelimit-input-tokens-remaining e anthropic-ratelimit-output-tokens-remaining. Aquele que indicar 0 no momento da requisição falha é o limite que foi atingido.
O `retry-after` está sempre presente em um RateLimitError?
Ele está presente no caso comum de um limite por minuto ser excedido. Trate sua ausência como um sinal que vale a pena investigar mais, pois pode indicar um tipo diferente de restrição, como um problema em nível de conta, em vez de um simples limite transitório.
Posso ter meu limite de tokens de saída atingido mesmo com um prompt curto?
Sim. Os limites de tokens de saída são impulsionados por max_tokens e pela quantidade que o modelo realmente gera, não pelo comprimento do prompt. Um prompt curto com um max_tokens alto e uma geração longa pode esgotar o limite de tokens de saída por si só.
Por quanto tempo devo observar antes de decidir que um padrão de 429 é sustentado em vez de disperso?
- Uma única janela não é suficiente; use pelo menos 15-30 minutos de dados deslizantes.
- Observe se a proporção de limite de taxa retorna a quase zero entre os picos (disperso) ou permanece elevada (sustentado).
Todos os modelos compartilham o mesmo limite de taxa?
Não. Os limites são rastreados por modelo, então o tráfego do Claude Sonnet 5 e do Claude Haiku 4.5 são regidos por buckets de limite separados, mesmo dentro da mesma conta.
Devo registrar todas as chamadas bem-sucedidas ou apenas as falhas?
Registre no mínimo os cabeçalhos de capacidade restante em cada chamada, sucesso ou falha, se você quiser ver um limite se aproximando antes que ele seja realmente atingido. Registrar apenas falhas significa que você sempre descobre depois do ocorrido.
O que significa se `retry-after` continuar crescendo em 429s consecutivos?
Esse é um forte sinal de sobrecarga sustentada, não de um pico. Um pico geralmente produz um retry-after que encolhe ou permanece estável à medida que a janela é liberada; um valor crescente sugere que o tráfego subjacente não diminuiu.
Um 429 é sempre culpa do chamador?
Não necessariamente. Um aumento súbito e legítimo de tráfego, um loop de retentativa do lado do cliente amplificando a carga, ou um teto de conta genuíno que não foi aumentado para acompanhar o crescimento podem produzir 429s sem que nenhuma requisição individual esteja em falta.
Requisições concorrentes de múltiplos processos podem dificultar o diagnóstico?
Sim. Se vários processos ou workers compartilham uma chave de API, o estado do limite de taxa é compartilhado entre todos eles, então um pico nos logs de um worker pode ser na verdade causado por outro worker completamente diferente. Centralize o registro de limites de taxa entre os processos, quando possível.
O que devo fazer imediatamente após confirmar que este é um teto de cota genuíno, e não um pico transitório?
Verifique o uso da sua conta e os limites de nível no console da Anthropic e considere se o tráfego recente justifica um aumento de nível, em vez de continuar retentando contra um teto que não será liberado por conta própria.
Para onde vou depois de diagnosticar o limite específico e o padrão de tráfego?
Uma vez que você saiba qual limite está sendo atingido e se é disperso ou sustentado, o artigo sobre retentativa e backoff cobre os padrões de resiliência, backoff exponencial com jitter, disjuntores e retentativas idempotentes, que abordam cada caso.
Relacionado
- Entendendo Por Que os Agentes Claude Falham em Produção - onde os 429s se encaixam na taxonomia mais ampla de falhas.
- Noções Básicas de Solução de Problemas e Confiabilidade - a base de logging e tratamento de exceções sobre a qual este artigo se constrói.
- Estratégias de Retentativa e Backoff Exponencial para Falhas Transitórias na API Claude - o que construir depois de confirmar a causa e o padrão.
- Modelo de Análise de Causa Raiz para Falhas de Agentes - documentando um incidente de 429 após sua resolução.
- Melhores Práticas de Solução de Problemas e Confiabilidade - a lista de verificação mais ampla na qual este diagnóstico se insere.
Versões de Stack: Escrito contra a linha de modelos Claude atual em ~junho de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (o padrão), e Claude Haiku 4.5 - e o SDK oficial
anthropicpara Python (última versão 0.x). Nomes de modelos, preços e versões de SDK mudam rapidamente - verifique os detalhes atuais em platform.claude.com/docs antes de confiar neles.