Nous limitions nos propres services
La limite de l'API de Mythex est de 300 requêtes par minute depuis une même adresse réseau. Cette limite existe pour nous protéger contre une personne ou un script qui bombarderait l'API. En production, elle a commencé à refuser nos propres services — la partie de notre edge qui sert les applications publiées et le service qui exécute l'agent IA — parce que chacun d'eux atteint l'API depuis seulement quelques adresses. Les requêtes qui portent notre identifiant interne sont maintenant exemptées, et tout le reste reste limité exactement comme avant.
Le symptôme
L'API a commencé à répondre à certains de nos appels internes par 429 Too Many Requests. Trois types d'appels étaient touchés, et chacun compte pour quelqu'un qui utilise Mythex :
- La recherche de l'application qui occupe un domaine personnalisé. Lorsqu'un visiteur ouvre une application publiée sur son propre domaine, notre edge demande à l'API où se trouve ce site. Un 429 à cette étape signifie un visiteur qui ne peut pas atteindre un site.
- L'enregistrement d'un tour d'agent en cours. Pendant que l'agent travaille, sa progression est sauvegardée au fil de l'eau, afin qu'une réponse survive à une actualisation ou à une connexion interrompue. Un 429 à cette étape signifie une progression qui n'a pas été sauvegardée.
- La vérification de l'accès à un aperçu. L'aperçu d'une application en construction est protégé, et ce contrôle interroge l'API. Un 429 à cette étape signifie un aperçu qui ne s'ouvre pas.
Aucun de ces appels ne venait de personnes qui utilisaient l'API. Tous venaient de nous.
Pourquoi c'est arrivé
Une limite par adresse repose sur une hypothèse : une adresse correspond à peu près à un appelant. Pour des personnes, c'est assez proche. Pour notre propre infrastructure, c'est très faux.
- Le service edge qui sert les applications publiées et les aperçus atteint l'API depuis quelques adresses sortantes partagées. Chaque visiteur de chaque application publiée, et chaque vérification d'aperçu, arrive donc en apparence depuis l'une de ces quelques adresses.
- L'orchestrateur — le service qui exécute les tours d'agent — atteint l'API depuis une seule adresse de conteneur. Chaque tour en cours, pour chaque utilisateur, partage cette adresse.
Le budget prévu pour une seule personne était donc réparti entre tout le trafic d'un service entier. Ces services l'ont épuisé ensemble, et le limiteur a fait ce pour quoi il était configuré : il les a refusés.
La correction
Nos propres services prouvent déjà qui ils sont. Chaque appel interne transporte un jeton interne, et chaque route de la section interne de l'API vérifie ce jeton avant d'agir.
Le limiteur utilise maintenant la même vérification. Une requête dont le jeton correspond au jeton interne figure sur une liste d'autorisation et n'est pas comptée dans le budget par adresse. Tout le reste est compté exactement comme avant : 300 requêtes par minute par adresse.
Deux détails ont évité que cela ne devienne une faille :
- Un mauvais jeton ne passe pas. La liste d'autorisation ne reconnaît que le vrai jeton interne. Une requête avec un jeton inventé est comptée et limitée comme toute autre, et les routes internes la rejettent avec
401 Unauthorized. - La limite elle-même n'a pas changé. Nous n'avons pas augmenté le nombre pour faire de la place. Cela aurait masqué le problème jusqu'à la prochaine hausse de trafic, et affaibli la protection pour le cas que la limite est censée couvrir.
Nous avons déplacé les réglages du limiteur dans une petite fonction et écrit des tests pour celle-ci. Le premier envoie 20 requêtes avec le jeton interne à un limiteur réglé sur 5, et attend que les 20 réussissent. Un autre envoie des requêtes ordinaires depuis une même adresse et attend que les cinq premières réussissent, puis que les suivantes soient refusées. Un troisième envoie des requêtes avec un jeton falsifié et attend qu'elles soient refusées de la même façon.
Ce que nous en avons retenu
- Les limites portent des hypothèses. « Une adresse, un appelant » est intégré à une limite par adresse. Cela cesse d'être vrai dès que vos propres services se trouvent derrière des adresses partagées — et c'est souvent le cas : répartiteurs de charge, réseaux de périphérie, conteneurs, réseaux de bureau.
- Distinguez votre propre trafic par identité, non par adresse. Les adresses indiquent par où le trafic arrive, pas qui l'a envoyé. Nous disposions déjà d'un identifiant qui prouve qu'un appel est le nôtre ; le limiteur ne le regardait tout simplement pas.
- Ne réglez pas le problème en augmentant le nombre. Une limite plus élevée aurait fait disparaître les 429 pendant un moment, protégé moins, et échoué à nouveau plus tard.
- Regardez qui est ralenti. Un 429 qui frappe votre propre service est un signalement sur vos limites, pas la preuve que le limiteur fonctionne.
Ce que cela signifie si vous construisez sur Mythex
Rien à changer de votre côté. Les applications publiées sur des domaines personnalisés, les tours d'agent et les aperçus ne dépendent plus de l'achalandage du reste de Mythex. Le trafic de votre application relève de votre application : la limite décrite ici s'applique à notre API, et non aux applications que vous publiez.
Si vous exploitez votre propre backend, le même piège existe pour toute limite de débit que vous ajoutez. Nos guides sur ce qu'est une API et sur la liste de contrôle de sécurité pour les applications construites avec l'IA sont de bons points de départ. Et pour un autre cas où notre propre infrastructure nous nuisait, lisez comment nous avons ramené les déploiements à zéro erreur 502.