Blog

Estábamos limitando nuestros propios servicios

La API de Mythex permite 300 peticiones por minuto desde una misma dirección de red. Ese límite existe para protegernos de una persona o un script que bombardee la API. En producción empezó a rechazar a nuestros propios servicios: la parte de nuestro edge que sirve las apps publicadas y el servicio que ejecuta el agente de IA, porque cada uno de ellos contacta con la API desde solo unas pocas direcciones. Las peticiones que llevan nuestra credencial interna están ahora exentas, y todos los demás siguen limitados exactamente como antes.

El síntoma

La API empezó a responder a algunas de nuestras llamadas internas con 429 Too Many Requests. Se vieron afectados tres tipos de llamada, y cada una importa a quien usa Mythex:

  • Buscar qué app vive en un dominio personalizado. Cuando un visitante abre una app publicada en su propio dominio, nuestro edge pregunta a la API dónde está ese sitio. Un 429 ahí es un visitante que no puede llegar a una web.
  • Guardar un turno del agente en ejecución. Mientras el agente trabaja, su progreso se guarda a medida que avanza, para que una respuesta sobreviva a una recarga o a una conexión caída. Un 429 ahí es progreso que no llegó a guardarse.
  • Comprobar el acceso a una vista previa. La vista previa de una app que estás construyendo tiene control de acceso, y ese control pregunta a la API. Un 429 ahí es una vista previa que no se abre.

Ninguna de estas llamadas la hacían personas a la API. Todas las hacíamos nosotros.

Por qué pasó

Un límite de peticiones por dirección hace una suposición: una dirección equivale más o menos a un solo cliente. Para las personas, es una aproximación razonable. Para nuestra propia infraestructura, está muy equivocada.

  • El servicio edge que sirve las apps publicadas y las vistas previas contacta con la API desde unas pocas direcciones de salida compartidas. Cada visitante de cada app publicada, y cada comprobación de vista previa, llega pareciendo que viene de una de esas pocas.
  • El orquestador, el servicio que ejecuta los turnos del agente, contacta con la API desde una sola dirección de contenedor. Cada turno en ejecución, de cada usuario, la comparte.

Así, el presupuesto pensado para una sola persona se repartía entre todo el tráfico de un servicio entero. Esos servicios lo agotaban entre ambos, y el limitador hizo lo que estaba configurado para hacer: los rechazó.

La solución

Nuestros propios servicios ya demuestran quiénes son. Cada llamada interna lleva un token interno, y cada ruta de la sección interna de la API comprueba ese token antes de hacer nada.

El limitador de peticiones ahora usa esa misma comprobación. Una petición cuyo token coincide con el interno está en una lista de permitidos y no cuenta para el presupuesto por dirección. Todo lo demás se cuenta exactamente como antes: 300 peticiones por minuto y por dirección.

Dos detalles evitaron que esto se convirtiera en un agujero:

  1. Un token incorrecto no obtiene ningún pase. La lista de permitidos solo coincide con el token interno real. Una petición con un token inventado se cuenta y se limita como cualquier otra, y las rutas internas la siguen rechazando con 401 Unauthorized.
  2. El límite en sí no cambió. No subimos el número para hacer sitio. Subirlo habría ocultado el problema hasta que el tráfico volviera a crecer, y habría debilitado la protección en el caso para el que existe el límite.

Trasladamos la configuración del limitador a una pequeña función y escribimos pruebas contra ella. Una envía 20 peticiones con el token interno a un limitador configurado para permitir 5, y espera que las 20 tengan éxito. Otra envía peticiones normales desde una dirección y espera que las cinco primeras tengan éxito y las siguientes sean rechazadas. Una tercera envía peticiones con un token falsificado y espera que se rechacen de la misma forma.

Lo que sacamos de todo esto

  • Los límites llevan suposiciones. «Una dirección, un cliente» está incorporado en un límite por dirección. Deja de ser cierto en cuanto tus propios servicios están detrás de direcciones compartidas, y muchos lo están: balanceadores de carga, redes edge, contenedores, redes de oficina.
  • Distingue tu propio tráfico por identidad, no por dirección. Las direcciones son por donde llega el tráfico, no quién lo envió. Ya teníamos una credencial que demuestra que una llamada es nuestra; el limitador simplemente no la estaba mirando.
  • No lo arregles subiendo el número. Un límite más alto habría hecho desaparecer los 429 durante un tiempo, habría protegido menos y habría vuelto a fallar más adelante.
  • Mira a quién se está limitando. Un 429 que cae sobre tu propio servicio es un informe de error sobre tus límites, no una señal de que el limitador funciona.

Qué significa si construyes en Mythex

No tienes que cambiar nada. Las apps publicadas en dominios personalizados, los turnos del agente y las vistas previas ya no dependen de lo ocupado que esté el resto de Mythex. El tráfico propio de tu app es asunto de tu app: el límite descrito aquí está en nuestra API, no en las apps que publicas.

Si mantienes un backend propio, la misma trampa se aplica a cualquier límite de peticiones que añadas. Nuestras guías sobre qué es una API y la lista de comprobación de seguridad para apps creadas con IA son un buen punto de partida. Y para otro caso en que nuestra propia infraestructura se estorbó a sí misma, consulta cómo conseguimos despliegues con cero errores 502.

Mythex · Pricing · Crea lo que quieras con IA · Plantillas de sitios web y apps · Mythex comparado · Glosario de creación de apps con IA · Herramientas gratuitas para crear apps con IA · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)