Sección 18
Ritmo y cuotas
El Gateway acota su tráfico en tres planos distintos, y confundirlos lleva a dimensionar mal: el ritmo es
cuántas peticiones por segundo acepta su credencial, la concurrencia es cuántas atiende a la vez, y los
créditos son cuánto puede gastar en el periodo. Un 429 puede venir de cualquiera de los tres, y el code
del cuerpo dice de cuál.
Ritmo por credencial
La cuenta es por clave de API, no por dirección IP: repartir la misma clave entre varias máquinas no multiplica su cupo, y perderla no le regala tráfico a quien la encuentre.
| Política | Cuota | Ventana |
|---|---|---|
burst | 15 peticiones | 1 segundo |
sustained | 600 peticiones | 60 segundos |
Las dos rigen a la vez, así que un pico de 15 en un segundo es legal pero no sostenible sesenta veces. La ventana es deslizante: el cupo se recupera de forma continua, no de golpe al cambiar de minuto.
Lea el saldo en la respuesta, no el reloj
Las respuestas correctas de /v1, y el rechazo por el techo de su clave, publican el estado en dos
cabeceras del borrador IETF httpapi-ratelimit-headers, que es el vocabulario al que converge la industria:
RateLimit-Policy: "burst";q=15;w=1, "sustained";q=600;w=60
RateLimit: "burst";r=14;t=1, "sustained";r=587;t=60q es la cuota y w la ventana en segundos; r es lo que le queda y t los segundos en que libera la
siguiente unidad. Regularse con r es mejor que contar peticiones en su lado: el saldo real ya tiene en cuenta
lo que gastaron sus otras máquinas con la misma clave.
Un r positivo no es una reserva. Es el saldo en el instante de esa respuesta, y otra máquina suya puede
consumirlo antes de su siguiente petición.
Cuando le frenan: hay DOS techos, y no traen lo mismo
Sobre /v1 actúan dos limitadores distintos. Los dos responden 429 y los dos traen Retry-After en
segundos, que es lo único que necesita para reintentar bien. Se diferencian en el code y en si hay saldo
que leer:
code | Qué techo es | Cómo se reparte | ¿Trae RateLimit? |
|---|---|---|---|
key_rate_limited | El de su clave | Por credencial | Sí. r=0 en la política que le frenó |
rate_limited | El de la plataforma | Por dirección IP de origen | No: el cupo no es suyo, es compartido |
Si llama desde una sola máquina, lo normal es encontrar primero el techo de la plataforma. El de su clave aparece cuando reparte la misma credencial entre varias máquinas, que es lo que ese límite existe para acotar.
Programe contra Retry-After, no contra el saldo. El saldo sirve para no llegar al rechazo; la cabecera
de espera sirve para salir de él, y está en los dos casos. Los otros tres 429 —concurrency_limit_reached,
call_concurrency_limit_reached y period_quota_exhausted— no se arreglan bajando el ritmo, así que mire el code antes de reintentar
(página 16).
Concurrencia y cupo del periodo: por cuenta y por entorno
Los otros dos planos no se cuentan por clave sino por cuenta, y hay un juego de techos para cada entorno:
las peticiones y llamadas en vuelo de ak_test_ no ocupan las ranuras de ak_live_. El dinero, en cambio,
no se separa: los dos entornos cobran y gastan del mismo saldo (página 14), y
ninguno tiene un techo de créditos propio. Lo que acota el gasto de un bucle de pruebas es el saldo y el tope de
gasto de la cuenta (página 16), no un cupo del entorno.
| Techo | Con el que se abre una cuenta en la beta, en cada entorno | Cuando se llena |
|---|---|---|
| Peticiones simultáneas | 10 | 429 concurrency_limit_reached, con Retry-After |
| Llamadas de voz simultáneas | 5 | 429 call_concurrency_limit_reached, con Retry-After |
| Créditos del periodo | sin techo: manda el saldo de la cuenta | — |
Son dos recursos distintos y no un alias: una petición síncrona ocupa su ranura segundos y no cuesta nada mientras espera, y una llamada ocupa un canal del proveedor y un flujo de audio durante minutos, con coste por minuto. Con un solo techo, cinco llamadas largas le dejarían sin poder transcribir un audio.
Si a su cuenta le fijamos un techo de créditos por periodo, hay dos rechazos y no son el mismo:
429 period_quota_exhausted, con Retry-After, cuando lo que queda del periodo no cubre la operación, y
409 request_exceeds_period_quota, sin Retry-After, cuando la operación no cabe ni con el periodo vacío.
Esperar arregla el primero; el segundo solo se arregla subiendo el techo.
El periodo es el mes natural en UTC, el mismo con el que se cuenta su saldo, para que un techo no se reinicie cuando el saldo no.
Los techos se cambian a petición. Si el suyo no coincide con esta tabla, manda el de su cuenta: pregúntenos antes de dimensionar contra los números de arriba.
Una cuenta sin cupo en un entorno no opera en ese entorno, y no responde 429 sino
403 gateway_not_enabled: la ausencia de techo no significa «sin límite». Es lo que hace que una cuenta
pueda estar admitida en pruebas y todavía no en producción, que es el estado normal mientras integra.
Cadencia de sondeo de un trabajo
GET /v1/jobs/{job_id} es gratis y no consume ranura de concurrencia, pero sí consume ritmo. Si sigue un
trabajo por sondeo en vez de por webhook, espere 2 segundos entre consultas y aumente la espera al doble
tras cada respuesta que siga queued o running, hasta un techo de 30 segundos. Un bucle sin espera agota la
ventana burst de toda su clave en un segundo y frena las peticiones que sí trabajan.
Con receptor de webhooks no hace falta sondear: el job.succeeded llega solo
(página 11).
Qué NO cuenta contra su ritmo
El transporte en streaming del asistente mantiene la conexión abierta y no repite peticiones, así que no gasta ventana mientras emite. Lo que sí la gasta es abrir el turno.