Diagnóstico de errores de límite de tasa 429 y agotamiento de cuota bajo carga
Un 429 de la API de Claude siempre significa lo mismo a nivel de protocolo: excediste un límite, pero el límite específico, la razón y la solución son diferentes cada vez. Diagnosticar un 429 correctamente, antes de tocar tu lógica de reintentos, es lo que separa una solución de cinco minutos de un incidente recurrente.
Resumen
La API de Claude aplica varios límites de tasa independientes a la vez: solicitudes por minuto, tokens de entrada por minuto y tokens de salida por minuto, cada uno rastreado por separado por modelo.
Una respuesta 429 te indica que se alcanzó un límite, pero las cabeceras de la respuesta te dicen cuál, y ese detalle cambia lo que realmente debes hacer al respecto.
Los límites de tasa también vienen en dos sabores que se ven idénticos desde el cliente pero requieren soluciones diferentes: un techo de cuota genuino de cuenta u organización, y un breve pico de tráfico concurrente que excede temporalmente tu rendimiento asignado.
Esta página te guía a través de la lectura de la señal que te da la API, la diferenciación de picos breves de sobrecarga sostenida, y la construcción del registro de diagnóstico mínimo que hace que la próxima tormenta de 429 sea una lectura rápida en lugar de un juego de adivinanzas.
Se detiene en el diagnóstico. Una vez que sepas qué límite estás alcanzando y cuál es la forma del tráfico, el artículo sobre reintentos y retrocesos cubre qué construir en respuesta.
Receta
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
import anthropic
client = anthropic.Anthropic()
try:
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Summarize this report."}],
)
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"))Cuándo usar esto:
- Tu aplicación devuelve intermitentemente 429 y necesitas saber si es un límite de recuento de solicitudes, tokens de entrada o tokens de salida antes de elegir una solución.
- Sospechas que un pico de solicitudes concurrentes, en lugar de un volumen sostenido, está activando el límite.
- Estás estableciendo una línea base antes de agregar lógica de reintentos y retrocesos, para poder medir si la solución realmente funcionó.
- Necesitas distinguir entre "nos quedamos sin cuota para el período de facturación" y "excedimos brevemente nuestra asignación por minuto".
Ejemplo de trabajo
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:
"""Extrae una firma estructurada de un RateLimitError para que pueda ser
registrada, agregada y 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("Draft a status update for the incident channel.")Lo que esto demuestra:
- Lectura de las cabeceras
anthropic-ratelimit-*para determinar qué límite específico (solicitudes, tokens de entrada o tokens de salida) provocó el 429, en lugar de tratar cada 429 de la misma manera. - Captura de
retry-afterpara saber cuánto tiempo recomienda la API esperar antes de intentarlo de nuevo. - Registro de una firma estructurada por evento, de modo que un pico de 429 produzca un conjunto de datos agregable en lugar de una pared de rastreos de pila idénticos.
- Conservación del
request_idpara correlación con el soporte de Anthropic o tu propio RCA si el patrón se repite.
Profundización
Cómo funciona
- La API de Claude rastrea los límites de tasa por organización y por modelo, en tres dimensiones independientes: solicitudes por minuto, tokens de entrada por minuto y tokens de salida por minuto.
- Una solicitud puede ser rechazada por exceder cualquiera de estas, incluso si las otras dos tienen margen, por lo que una sola línea de registro "límite de tasa alcanzado" sin el detalle de la cabecera casi no te dice nada.
- La cabecera
retry-afteres la recomendación de la propia API sobre cuánto esperar, expresada en segundos, y tiene en cuenta el límite específico que se excedió. - Los techos de cuota (un límite estricto vinculado a tu nivel de cuenta o límite de gasto) se ven idénticos a un límite temporal por minuto en el tipo de excepción, pero no se aclaran por sí solos como lo hace un límite por minuto, requieren una mejora de nivel o una conversación de soporte.
Firmas de límite de tasa de un vistazo
| Cabecera | Significado | Qué te dice |
|---|---|---|
anthropic-ratelimit-requests-remaining | Solicitudes restantes en la ventana actual | 0 significa que estás alcanzando el techo del recuento de solicitudes |
anthropic-ratelimit-input-tokens-remaining | Tokens de entrada restantes en la ventana actual | 0 significa que los prompts largos o el contexto son el impulsor |
anthropic-ratelimit-output-tokens-remaining | Tokens de salida restantes en la ventana actual | 0 significa que un max_tokens alto o generaciones largas son el impulsor |
retry-after | Segundos hasta que la API espera que reintentes | Un valor corto (menos de unos pocos segundos) generalmente significa un pico; un valor largo a menudo significa sobrecarga sostenida |
Tráfico con picos vs. Sostenido
- Con picos: un pico corto, a menudo causado por un trabajo por lotes, una tormenta de reintentos o muchos usuarios que activan una acción a la vez (por ejemplo, un despliegue que restablece las cachés del lado del cliente y causa una estampida de solicitudes). La firma es un clúster de 429 en una ventana de tiempo estrecha, seguido de una recuperación limpia.
- Sostenido: tu tráfico estable ha crecido más allá de lo que tu nivel actual o concurrencia configurada soporta. La firma es una tasa de 429 que no se recupera completamente entre ventanas, se degrada, se recupera parcialmente y luego se degrada nuevamente.
- Grafica las ocurrencias de 429 en una ventana móvil de 5 minutos antes de decidir cuál estás viendo. Un solo gráfico de pico no es suficiente para distinguir entre pico y sostenido; necesitas ver si la línea base en sí está aumentando.
# Una forma mínima de distinguir entre pico y sostenido: rastrea la relación
# de llamadas con límite de tasa con el total de llamadas en una ventana móvil y observa
# si la línea base se recupera entre 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)Techos de cuota vs. Límites por minuto
| Señal | Límite por minuto | Techo de cuota de cuenta/organización |
|---|---|---|
| Recuperación | Se aclara dentro de la ventana (típicamente 60 segundos) | No se aclara hasta que se reinicia el período de facturación o cambia el nivel |
retry-after | Usualmente segundos | Puede estar ausente o no ser significativamente útil |
| Solución | Retroceso, control de concurrencia, lotes de solicitudes | Solicitar un aumento de nivel, revisar gastos, agregar capacidad en la consola |
Trampas comunes
-
Tratar cada 429 como el mismo problema. Registrar "límite de tasa alcanzado" sin el desglose de la cabecera oculta si es un límite de recuento de solicitudes, tokens de entrada o tokens de salida. Solución: siempre registra las tres cabeceras
anthropic-ratelimit-*-remainingjunto con la excepción. -
Confundir un pico con sobrecarga sostenida. Una sola alerta que se dispara durante un pico de cinco minutos puede desencadenar una actualización de capacidad que en realidad no soluciona un patrón de pico recurrente. Solución: rastrea la relación móvil durante al menos 15-30 minutos antes de concluir que es sostenido.
-
Ignorar
retry-after. Implementar tu propio intervalo de retroceso fijo cuando la API ya te dice cuánto esperar desperdicia reintentos y puede empeorar el límite. Solución: lee y respetaretry-aftercuando esté presente; trátalo como un mínimo, no como un máximo. -
No separar los límites por modelo. Si tu tráfico llama tanto a Sonnet como a Haiku, un 429 en el límite de un modelo no significa que el otro modelo también esté restringido. Solución: etiqueta los registros de diagnóstico con el parámetro
modelutilizado en la solicitud que falló. -
Diagnosticar solo con registros del lado del cliente. El tiempo del lado del cliente puede hacer que una respuesta lenta y saludable parezca idéntica a un reintento en cola después de un 429. Solución: siempre captura la excepción real y sus cabeceras, no solo el tiempo de solicitud transcurrido.
-
Asumir que el agotamiento de la cuota se autocurará como un límite por minuto. Esperar y reintentar contra un techo de cuota de cuenta genuino solo produce más 429. Solución: verifica si
retry-afterestá presente y es corto antes de asumir que esto es transitorio; si está ausente o es inusualmente largo, verifica el estado de la cuota de tu cuenta en la consola.
Alternativas
| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
| Inspección manual de cabeceras (este artículo) | Necesitas entender la causa exacta antes de cambiar el comportamiento | Ya conoces la causa y solo necesitas resiliencia, usa el artículo de reintentos/retrocesos en su lugar |
| Un panel de límites de tasa dedicado / pipeline de métricas | Tienes incidentes recurrentes de 429 y necesitas datos de tendencias históricas | Estás diagnosticando un pico por primera vez o único, un panel es excesivo para un solo incidente |
| Solicitar un aumento de cuota/nivel | El diagnóstico confirma sobrecarga sostenida contra un techo de cuota real | El patrón es con picos, un techo más alto solo retrasa el mismo problema |
Preguntas frecuentes
¿Cuál es la diferencia entre un límite de tasa y una cuota?
- Un límite de tasa es un techo móvil por minuto en solicitudes, tokens de entrada o tokens de salida, rastreado por modelo.
- Una cuota es típicamente un límite de cuenta u organización vinculado a tu nivel de uso o límite de gasto, y no se reinicia cada minuto.
¿Cómo sé qué límite específico causó un 429 dado?
Verifica las cabeceras de respuesta anthropic-ratelimit-requests-remaining, anthropic-ratelimit-input-tokens-remaining y anthropic-ratelimit-output-tokens-remaining. Cualquiera que lea 0 en el momento de la solicitud fallida es el límite que se alcanzó.
¿Está `retry-after` siempre presente en un RateLimitError?
Está presente en el caso común de que se exceda un límite por minuto. Trata su ausencia como una señal que vale la pena investigar más a fondo, ya que puede indicar un tipo diferente de restricción, como un problema a nivel de cuenta, en lugar de un simple límite transitorio.
¿Puedo tener un límite de tasa en tokens de salida incluso con un prompt corto?
Sí. Los límites de tokens de salida están impulsados por max_tokens y cuánto genera realmente el modelo, no por la longitud del prompt. Un prompt corto con un max_tokens alto y una generación larga puede agotar el límite de tokens de salida por sí solo.
¿Cuánto tiempo debo observar antes de decidir que un patrón 429 es sostenido en lugar de con picos?
- Una sola ventana no es suficiente; usa al menos 15-30 minutos de datos móviles.
- Observa si la relación con límite de tasa vuelve a estar cerca de cero entre picos (con picos) o se mantiene elevada (sostenido).
¿Comparte cada modelo el mismo límite de tasa?
No. Los límites se rastrean por modelo, por lo que el tráfico de Claude Sonnet 5 y Claude Haiku 4.5 se rige por cubos de límites separados incluso dentro de la misma cuenta.
¿Debo registrar cada llamada exitosa o solo los fallos?
Registra como mínimo las cabeceras de capacidad restante en cada llamada, exitosa o fallida, si quieres ver un límite acercándose antes de que se alcance realmente. Registrar solo los fallos significa que siempre te enteras después del hecho.
¿Qué significa si `retry-after` sigue creciendo en 429s consecutivos?
Esa es una fuerte señal de sobrecarga sostenida, no de un pico. Un pico típicamente produce un retry-after que se encoge o se mantiene plano a medida que la ventana se aclara; un valor creciente sugiere que el tráfico subyacente no se ha retrocedido.
¿Es un 429 siempre culpa del llamador?
No necesariamente. Un aumento repentino de tráfico legítimo, un bucle de reintentos del lado del cliente que amplifica la carga, o un techo de nivel de cuenta genuino que no se ha elevado para igualar el crecimiento pueden producir 429 sin que ninguna solicitud individual sea la culpable.
¿Las solicitudes concurrentes de múltiples procesos dificultan el diagnóstico?
Sí. Si varios procesos o trabajadores comparten una clave de API, el estado del límite de tasa se comparte entre todos ellos, por lo que un pico en los registros de un trabajador puede ser causado en realidad por otro trabajador completamente diferente. Centraliza tu registro de límites de tasa entre procesos cuando sea posible.
¿Qué debo hacer inmediatamente después de confirmar que se trata de un techo de cuota genuino, no de un pico transitorio?
Verifica el uso y los límites de nivel de tu cuenta en la consola de Anthropic, y considera si el crecimiento reciente del tráfico justifica un aumento de nivel, en lugar de continuar reintentando contra un techo que no se aclarará por sí solo.
¿A dónde voy después de diagnosticar el límite específico y el patrón de tráfico?
Una vez que sepas qué límite se está alcanzando y si es con picos o sostenido, el artículo sobre reintentos y retrocesos cubre los patrones de resiliencia, retroceso exponencial con jitter, disyuntores y reintentos idempotentes, que abordan cada caso.
Relacionado
- Entender por qué los agentes de Claude fallan en producción - dónde encajan los 429 en la taxonomía general de fallos.
- Fundamentos de solución de problemas y confiabilidad - la base de registro y manejo de excepciones sobre la que se construye este artículo.
- Estrategias de reintento y retroceso exponencial para fallos transitorios de la API de Claude - qué construir una vez que hayas confirmado la causa y el patrón.
- Plantilla de análisis de causa raíz para fallos de agentes - documentación de un incidente 429 una vez resuelto.
- Mejores prácticas de solución de problemas y confiabilidad - la lista de verificación más amplia en la que se basa este diagnóstico.
Versiones de pila: Escrito contra la línea de modelos de Claude actual a partir de ~junio de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (el predeterminado), y Claude Haiku 4.5 - y el SDK oficial de Python
anthropic(última versión 0.x). Los nombres de modelos, precios y versiones del SDK cambian rápidamente; verifica los detalles actuales en platform.claude.com/docs antes de confiar en ellos.