Rate limits de una API de multas: 429, cuotas y reintentos
Un 429 puede señalar una ventana agotada, demasiada concurrencia o protección temporal, mientras una cuota comercial mide otro período. Un contrato explícito evita que el cliente reintente todos los casos igual.
Por Marco Ferreiro ·
Una integración de flota recibe 429 Too Many Requests y tiene dos reacciones frecuentes: detener todo hasta el mes siguiente o reintentar inmediatamente. Ambas pueden ser incorrectas. El código informa que una política de ritmo no aceptó esa solicitud, pero no identifica por sí solo cuál política, cuánto esperar ni qué ocurrió con la cuota comercial.
Un rate limit útil de una API de infracciones debe poder interpretarse sin exponer el funcionamiento interno de las defensas.
Separar ventana, concurrencia y cuota contractual
Una API puede aplicar controles superpuestos:
- solicitudes por segundo para evitar ráfagas;
- trabajos concurrentes por empresa;
- consultas por día o mes según el plan;
- protección temporal de un recurso costoso;
- medidas de seguridad frente a patrones anómalos.
La cuota comercial puede seguir disponible aunque una ráfaga agote la ventana de un segundo. También puede ocurrir lo contrario: el cliente respeta el ritmo, pero ya consumió las patentes de su plan.
El contrato debería nombrar la unidad. “100 consultas” no aclara si una búsqueda por patente cuenta una vez, por jurisdicción iniciada o según el costo de cada fuente.
Qué comunica realmente 429
RFC 6585 define 429 para indicar que el usuario envió demasiadas solicitudes en un período. La respuesta puede incluir Retry-After. RFC 9110 permite expresar esa espera como segundos o fecha HTTP.
El cuerpo debería ser un problema estructurado siguiendo RFC 9457, por ejemplo con type, title, status, detail y un identificador de instancia. Se pueden agregar campos documentados como policy o scope, sin revelar reglas que faciliten evadir controles.
{
"type": "https://api.example/errors/rate-limit",
"title": "Límite temporal alcanzado",
"status": 429,
"policy": "requests-per-minute",
"scope": "tenant",
"traceId": "trc_8ab..."
}
La respuesta no debe incluir patente, CUIT ni email en la URL del tipo, el detalle o la traza.
Retry-After marca una pausa, no una promesa
Cuando el servidor conoce una espera razonable, Retry-After evita que cada flota adivine. Si informa 20 segundos, el consumidor no debería volver antes. Puede agregar jitter después de ese mínimo para no sincronizarse con otras integraciones.
Al vencer el intervalo, la próxima solicitud todavía puede ser rechazada: cambió la capacidad, otra aplicación del mismo tenant consumió la ventana o existe una política diferente. Por eso la espera no es un turno reservado.
Si el encabezado falta o es inválido, el cliente aplica su propia espera creciente con techo. Nunca debería entrar en un bucle sin demora.
RateLimit describe la política observable
El grupo HTTPAPI del IETF mantiene un Internet-Draft que define campos RateLimit para comunicar políticas y disponibilidad de cuota. Al 14 de agosto de 2026 no es todavía un RFC publicado, pero permite diseñar y probar un contrato explícito sin presentarlo como estándar definitivo.
Esos valores son orientativos. No garantizan que la siguiente solicitud funcione y pueden representar una política seleccionada entre varias. El servidor debe documentar la partición: por credencial, empresa, jurisdicción o unidad de consumo.
Si conviven Retry-After y un reinicio de RateLimit, el cliente prioriza la instrucción de espera aplicable al rechazo. No debería sumar tiempos de manera ciega ni tratar “restante 0” como saldo mensual si la política es de un minuto.
Reintentar sin duplicar trabajo
Antes de repetir, el cliente necesita saber si la operación llegó a crear la consulta de esa patente. Un 429 generado antes de aceptar el trabajo puede reintentarse; un timeout después de la aceptación es ambiguo.
Las creaciones deberían admitir una clave de idempotencia o un identificador estable. Así, el mismo intento lógico no consume dos consultas ni dispara dos recorridos por jurisdicciones.
Para leer un acta ya obtenida, el reintento suele ser seguro, pero debe respetar la pausa. Para comandos, el contrato define explícitamente la semántica. “Es POST” no alcanza para decidir.
Un orquestador también debe aislar empresas. El límite de una flota no debería congelar el tráfico de todas ni hacer que una cola global reintente a la vez.
Errores que no deben representarse como 429
Una credencial sin permisos corresponde a autenticación o autorización, no a cuota. Una fuente de multas caída debe aparecer en el resultado parcial de la consulta, no como rate limit del cliente. Un cuerpo inválido es un error de validación. Y una cuenta sin saldo contractual puede necesitar un código de negocio documentado, aunque la API decida acompañarlo con un estado HTTP específico.
Usar 429 para todo impide a la flota elegir una acción correcta. El resultado suele ser una tormenta de reintentos que agrava el problema original.
Prueba de laboratorio con clientes concurrentes
Antes de publicar la política, simulá al menos cuatro escenarios: ráfaga breve, cuota diaria agotada, concurrencia máxima y Retry-After inválido. Usá patentes y resultados ficticios.
Medí solicitudes aceptadas, rechazos por política, demora efectiva, trabajos duplicados y concentración de reintentos por segundo. Verificá que:
- ningún cliente vuelva antes de
Retry-After; - el jitter distribuya la recuperación;
- la clave de idempotencia evite duplicados;
- el error permita distinguir ventana y cuota;
- las métricas no usen datos personales como etiquetas.
El objetivo no es publicar cuántas defensas internas existen. Es demostrar que un cliente bien comportado puede recuperarse sin adivinar y que un rechazo temporal nunca se transforma en “consulta sin multas”.
Un rate limit interpretable coordina capacidad, contrato y reintentos. Cuando cada capa tiene nombre, unidad y evidencia, el ERP sabe si esperar, reducir concurrencia, renovar su plan o pedir intervención.
Metodología
- Alcance
- Contrato HTTP para límites de una API multiempresa de consultas, sin publicar umbrales internos de defensa ni depender de un proveedor.
- Unidad de análisis
- Una cuota consumida y cada rechazo 429 atribuido a una política documentada, partición y ventana determinadas.
- Cobertura
- Recomendaciones basadas en los RFC oficiales de HTTP y Problem Details, más el Internet-Draft activo de RateLimit consultado el 14 de agosto de 2026.
Limitaciones
- El algoritmo de aplicación, la capacidad y los umbrales antiabuso son decisiones operativas que no deben inferirse de ejemplos.
- Los campos de límite ayudan a coordinar clientes, pero no constituyen una garantía de servicio ni reemplazan el contrato comercial.
Fuentes
- RFC 6585 — Additional HTTP Status Codes — RFC Editor (consultada el )
- RFC 9110 — HTTP Semantics — RFC Editor (consultada el )
- Internet-Draft activo — RateLimit header fields for HTTP — Internet Engineering Task Force (consultada el )
- RFC 9457 — Problem Details for HTTP APIs — RFC Editor (consultada el )
Preguntas frecuentes
¿Todo HTTP 429 significa que se agotó la cuota mensual contratada?
No. Puede corresponder a una ventana de segundos, concurrencia, protección por recurso o saturación. El error debe identificar la política sin revelar controles de seguridad sensibles.
¿La disponibilidad informada en RateLimit garantiza que la próxima solicitud será aceptada?
No. El borrador del IETF trata esos campos como orientación para el cliente; pueden existir otras políticas y el estado puede cambiar entre respuestas.
¿Se debe reintentar automáticamente cualquier 429?
Sólo si la operación y el contrato lo permiten. El cliente debe respetar Retry-After, aplicar límites propios y evitar duplicar una operación cuyo resultado anterior sea incierto.
¿Un límite debe contarse por request o por consulta de jurisdicción?
El contrato debe declararlo. Una búsqueda puede consumir una unidad, varias fuentes o un costo ponderado. Sin una unidad explícita, límite y saldo no son interpretables.
Notas relacionadas
Cobertura de una API: cómo comunicar fuentes caídas y resultados parciales
Una integración de infracciones necesita informar qué fuentes respondió, cuáles fallaron y si el resultado es completo. Un cero sin cobertura comprobada puede inducir decisiones incorrectas.
Timeout no significa “sin multas”: cómo informar resultados parciales en una integración
Cuando una fuente no responde, el resultado es parcial o indeterminado, nunca cero. Un contrato explícito permite reintentar, alertar y decidir sin producir falsos negativos.
Webhooks de nuevas multas: idempotencia, reintentos y trazabilidad
Un webhook confiable puede llegar más de una vez, demorarse o fallar después de ser procesado. El diseño debe deduplicar eventos, reintentar con límites y conservar evidencia de punta a punta.