Configuración

Idioma

Rate Limiting de APIs de IA: Cómo funciona y cómo gestionarlo

L
LemonData
·26 de febrero de 2026·650 vistas
Rate Limiting de APIs de IA: Cómo funciona y cómo gestionarlo

Todas las AI API tienen rate limits. Toparse con ellos en desarrollo es molesto. Toparse con ellos en producción y sus usuarios verán errores, streams parciales y tiempos de espera que parecen aleatorios hasta que se inspecciona el patrón.

El error principal es tratar el rate limiting como un único problema. Por lo general, se trata de cuatro problemas diferentes que se esconden tras el mismo 429:

  • requests per minute (solicitudes por minuto)
  • tokens per minute (tokens por minuto)
  • concurrent in-flight requests (solicitudes concurrentes en curso)
  • account-level or project-level quota exhaustion (agotamiento de cuota a nivel de cuenta o proyecto)

Si construye su solución pensando solo en uno de ellos, los demás seguirán afectándole.

Si aún se encuentra en la etapa de migración de proveedor, lea primero la guía de migración. Si está evaluando si un gateway ayuda con el fallback y la carga operativa, la comparativa de OpenRouter es la mejor lectura complementaria.

Qué significan realmente los Rate Limits

Límites de solicitudes (Request limits)

Este es el más obvio. Envió demasiadas solicitudes en un intervalo de tiempo corto.

Límites de tokens (Token limits)

Este es el que los equipos suelen subestimar. Un solo prompt largo puede consumir tanto presupuesto como muchas solicitudes pequeñas. Si de repente añade un prompt de sistema de 20 KB, el recuento de solicitudes puede parecer saludable mientras que el presupuesto de tokens ya se ha agotado.

Límites de concurrencia (Concurrency limits)

Algunos proveedores y gateways aceptan perfectamente su promedio por minuto hasta que abre cincuenta streams a la vez. El plan de rate es correcto, pero la forma del pico (burst) no lo es.

Agotamiento de cuota o saldo (Quota exhaustion)

A menudo aparece como un síntoma de “rate limit” en los dashboards porque el resultado operativo es el mismo: las llamadas dejan de tener éxito. Pero la solución es diferente. El backoff es inútil si el problema es un saldo de cero.

Cómo aplican los límites los proveedores habitualmente

Los números exactos cambian con el tiempo, por lo que codificar una tabla de precios pública en la documentación de su aplicación envejece mal. El patrón estable es este:

  • Los proveedores al estilo OpenAI suelen exponer headers de solicitudes y tokens, y ajustan su límite máximo en función del historial de la cuenta o del nivel de uso.
  • Los proveedores al estilo Anthropic suelen aplicar tanto el throughput a nivel de minuto como límites de proyecto más amplios, especialmente en modelos de gama alta.
  • Los proveedores al estilo Google a menudo separan el comportamiento del nivel gratuito del nivel de pago y pueden variar los límites drásticamente según la familia de modelos.
  • Los agregadores añaden una capa más de límites sobre las restricciones de los proveedores originales (upstream), pero a cambio pueden redirigir a otros canales cuando un upstream está temporalmente saturado.

Trate los límites de los proveedores como configuración dinámica, no como constantes.

Lectura de los Headers de Rate Limit

Todos los principales proveedores devuelven información sobre el rate limit en los headers de la respuesta:

x-ratelimit-limit-requests: 500
x-ratelimit-remaining-requests: 499
x-ratelimit-reset-requests: 60s
x-ratelimit-limit-tokens: 200000
x-ratelimit-remaining-tokens: 199500

Utilice estos headers de forma proactiva. No espere a un error 429 para reducir la velocidad.

El hábito operativo que busca es sencillo:

  1. Registre los headers cuando la operación tenga éxito, no solo cuando falle.
  2. Genere alertas cuando la capacidad restante caiga por debajo de un umbral.
  3. Moldee el tráfico antes de que la siguiente solicitud cruce la línea.

Si solo consulta los headers después de un fallo, ya va con retraso.

Construcción de la lógica de reintento (Retry Logic)

La forma incorrecta

# Don't do this
import time

def call_api(messages):
    while True:
        try:
            return client.chat.completions.create(
                model="gpt-4.1",
                messages=messages
            )
        except Exception:
            time.sleep(1)  # Fixed delay, no backoff, catches everything

Problemas: no hay exponential backoff, captura errores que no son reintentables, no hay límite máximo de reintentos, no hay jitter.

La forma correcta

import time
import random
from openai import RateLimitError, APIError, APIConnectionError

def call_with_retry(messages, model="gpt-4.1", max_retries=3):
    """Retry with exponential backoff and jitter."""
    for attempt in range(max_retries + 1):
        try:
            return client.chat.completions.create(
                model=model,
                messages=messages
            )
        except RateLimitError as e:
            if attempt == max_retries:
                raise
            # Use retry_after from response if available
            wait = getattr(e, 'retry_after', None)
            if wait is None:
                wait = (2 ** attempt) + random.uniform(0, 1)
            print(f"Rate limited. Waiting {wait:.1f}s (attempt {attempt + 1})")
            time.sleep(wait)
        except APIConnectionError:
            if attempt == max_retries:
                raise
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(wait)
        except APIError as e:
            # Don't retry client errors (400, 401, 403)
            if e.status_code and 400 <= e.status_code < 500:
                raise
            if attempt == max_retries:
                raise
            time.sleep((2 ** attempt) + random.uniform(0, 1))

Principios clave:

  • Exponential backoff: 1s, 2s, 4s, 8s
  • Jitter: se añade un valor aleatorio de 0-1s para evitar el efecto de "manada atronadora" (thundering herd)
  • Respetar el header retry_after cuando se proporcione
  • No reintentar errores del cliente (solicitud incorrecta, fallo de autenticación)
  • Establecer un recuento máximo de reintentos

Dos reglas de producción adicionales son importantes:

  • nunca reintente indefinidamente en un endpoint de streaming
  • nunca reintente una solicitud que ya esté vinculada a efectos secundarios visibles para el usuario, a menos que la operación sea idempotente

Las chat completions suelen ser seguras de reintentar. Los efectos secundarios activados por herramientas (tools) a menudo no lo son.

Versión Async

import asyncio
import random
from openai import AsyncOpenAI, RateLimitError

async_client = AsyncOpenAI(
    api_key="sk-lemon-xxx",
    base_url="https://api.lemondata.cc/v1"
)

async def call_with_retry_async(messages, model="gpt-4.1", max_retries=3):
    for attempt in range(max_retries + 1):
        try:
            return await async_client.chat.completions.create(
                model=model,
                messages=messages
            )
        except RateLimitError:
            if attempt == max_retries:
                raise
            wait = (2 ** attempt) + random.uniform(0, 1)
            await asyncio.sleep(wait)

Moldear el tráfico antes de que se convierta en una tormenta de reintentos

La lógica de reintento es solo la mitad de la solución. Si su upstream ya está sobrecargado, los reintentos pueden convertir un pico de tráfico en una interrupción del servicio autoinfligida.

Tres controles marcan la diferencia:

1. Cola por tenant o usuario

Si un cliente inicia un trabajo por lotes masivo, no querrá que todos los demás clientes hereden el radio de impacto.

2. Limitar los streams concurrentes

Los endpoints de streaming son fáciles de subestimar porque cada solicitud "parece" barata mientras permanece abierta durante mucho tiempo.

3. Recortar los prompts antes de enviarlos

Los límites de tokens suelen ser el techo real. Un prompt que es el doble de largo reduce el throughput seguro aproximadamente a la mitad.

Token Bucket del lado del cliente

Para aplicaciones de alto throughput, implemente rate limiting en el lado del cliente para evitar alcanzar los límites del servidor:

import time
import asyncio

class TokenBucket:
    def __init__(self, rate: float, capacity: int):
        self.rate = rate          # tokens per second
        self.capacity = capacity  # max burst size
        self.tokens = capacity
        self.last_refill = time.monotonic()

    async def acquire(self, tokens: int = 1):
        while True:
            now = time.monotonic()
            elapsed = now - self.last_refill
            self.tokens = min(
                self.capacity,
                self.tokens + elapsed * self.rate
            )
            self.last_refill = now

            if self.tokens >= tokens:
                self.tokens -= tokens
                return
            # Wait for enough tokens
            wait = (tokens - self.tokens) / self.rate
            await asyncio.sleep(wait)

# 500 requests per minute = ~8.3 per second
limiter = TokenBucket(rate=8.0, capacity=20)

async def rate_limited_call(messages, model="gpt-4.1"):
    await limiter.acquire()
    return await async_client.chat.completions.create(
        model=model,
        messages=messages
    )

Los token buckets son útiles cuando conoce su límite máximo. Son aún mejores cuando los ajusta a partir de los datos observados en los headers en lugar de una estimación codificada.

Fallback de modelo ante Rate Limits

Cuando su modelo principal tiene el rate limitado, recurra a una alternativa:

FALLBACK_CHAIN = [
    "claude-sonnet-4-6",
    "gpt-4.1",
    "gpt-4.1-mini",
]

async def call_with_fallback(messages):
    for model in FALLBACK_CHAIN:
        try:
            return await async_client.chat.completions.create(
                model=model,
                messages=messages
            )
        except RateLimitError:
            continue
    raise Exception("All models rate limited")

Aquí es donde los gateways de modelos ayudan, pero solo si el fallback es deliberado. No salte silenciosamente de un modelo de razonamiento premium a un modelo económico diminuto sin pensar en el impacto para el usuario.

Una cadena de fallback razonable es:

  • mismo proveedor, modelo hermano más pequeño
  • familia de modelos equivalente de otro proveedor
  • solo entonces un modelo más barato o con menor contexto

Si mezcla el “fallback por disponibilidad” con el “fallback por coste” en un solo paso, la depuración se vuelve complicada rápidamente.

Monitoreo del uso de Rate Limits

Realice un seguimiento de su consumo de rate limits para detectar problemas antes de que afecten a los usuarios:

import logging

def log_rate_limits(response):
    headers = response.headers
    remaining = headers.get("x-ratelimit-remaining-requests")
    limit = headers.get("x-ratelimit-limit-requests")
    if remaining and int(remaining) < int(limit) * 0.1:
        logging.warning(
            f"Rate limit warning: {remaining}/{limit} requests remaining"
        )

Establezca alertas cuando la capacidad restante caiga por debajo del 10%. Esto le da tiempo para implementar el throttling antes de que los usuarios vean errores 429.

También debería registrar:

  • ID de solicitud
  • modelo
  • estimación del tamaño de entrada
  • duración del stream
  • recuento de reintentos
  • resultado final (success, rate_limited, network_error, quota_exhausted)

Sin esos campos, los incidentes de rate limit se convierten en meras conjeturas.

Una lista de verificación de producción sencilla

Antes de considerar que su chatbot o agente es “seguro frente a rate limits”, verifique estos cinco puntos:

  1. Existe una política de reintentos limitada tanto para rutas síncronas como asíncronas.
  2. Registra los headers de rate limit en las respuestas exitosas.
  3. Existe un moldeado de tráfico por usuario o por tenant antes de la llamada al upstream.
  4. Existe al menos un modelo de fallback validado.
  5. El frontend recibe un estado de error limpio en lugar de un stream colgado.

Si está construyendo la aplicación completa y no solo la primitiva de reintento, la guía de chatbot con una sola clave muestra cómo encajan estas piezas en un servicio FastAPI real.

Resumen

El rate limiting no es un caso aislado. Es una condición operativa normal para cualquier producto de AI con uso real. Los equipos que lo manejan bien no tienen límites mágicamente más altos. Tratan el throughput, los reintentos y el fallback como parte del diseño de la aplicación desde el principio.

Cree una API key en LemonData, pruebe su ruta de reintento antes del tráfico de producción y prepárese para el próximo 429 antes de que llegue.

Estrategia Cuándo usarla
Exponential backoff Siempre (base)
Rate limiter en el cliente Apps de alto throughput (>100 RPM)
Fallback de modelo Apps en producción con requisitos de SLA
Monitoreo proactivo Cualquier despliegue en producción
Batch API Cargas de trabajo que no son en tiempo real

El objetivo no es evitar los rate limits por completo. Es manejarlos con elegancia para que sus usuarios nunca lo noten.


Construya aplicaciones de AI resilientes: lemondata.cc ofrece enrutamiento multicanal que gestiona automáticamente los rate limits de los proveedores. Una sola API key, más de 300 modelos.

Share: