Se connecterContactCommencer gratuitement
Reliability and Routing30 juillet 2026Flatkey Team

Explication des limites de débit des LLM : RPM, TPM et tentatives de réessai

Comprenez le RPM, le TPM, les erreurs 429, la planification de capacité, les files d’attente, l’exponentiel backoff, les budgets de réessai et le routage de secours pour les API LLM en production.

Explication des limites de débit des LLM : RPM, TPM et tentatives de réessai

Les limites de débit des LLM déterminent la quantité de trafic que votre application peut envoyer à un modèle dans une fenêtre de temps donnée. Les deux limites que les ingénieurs rencontrent le plus souvent sont RPM (requêtes par minute) et TPM (jetons par minute). Une charge de travail peut rester sous l’une et dépasser l’autre.

Cette distinction est importante. Si vous traitez chaque 429 comme un simple problème générique de nombre de requêtes, vous risquez d’ajouter des tentatives de réessai qui augmentent la pression en jetons, allongent la latence et aggravent une panne. Une conception sûre en production identifie d’abord la ressource contrainte, puis choisit entre le lissage du trafic, la mise en file d’attente, les tentatives de réessai, la réduction du nombre de jetons ou l’acheminement ailleurs.

Ce guide explique les mécanismes, fournit des formules de planification de capacité et inclut un modèle de réessai TypeScript borné pour les API compatibles avec OpenAI.

RPM vs TPM : la réponse rapide

Limite Mesure Charges de travail qui la saturent en premier Meilleure première réponse
RPM Requêtes admises pendant une fenêtre de temps définie par le fournisseur Nombreux petits appels, boucles d’outils d’agent, évaluations à forte diffusion Lisser les requêtes, regrouper les tâches ou mettre les pics en file d’attente
TPM Jetons d’entrée et/ou de sortie admis pendant une fenêtre de temps Contexte long, grandes sorties, prompts à forte récupération, évaluations parallèles Réduire le volume de jetons, plafonner la sortie ou orienter vers une autre capacité
RPD Requêtes par jour Explorations planifiées, évaluations hors ligne à grande échelle, charges de travail en offre gratuite Replanifier ou augmenter le niveau de service
Requêtes concurrentes Requêtes en cours à un instant donné Générations lentes et charges de travail en streaming Limiter les workers et appliquer le backpressure
429 Une limite ou une politique de capacité a rejeté la requête Toute charge de travail dépassant un quota actif Qualifier l’erreur avant de réessayer

Le RPM contrôle la fréquence. Le TPM contrôle le débit. La concurrence contrôle le travail simultané. Ils interagissent, mais ne sont pas interchangeables.

Pourquoi une requête peut échouer en dessous de la limite annoncée

Une limite publiée comme 600 RPM ne signifie pas nécessairement qu’un client peut envoyer 600 requêtes dans la première seconde de chaque minute. Les fournisseurs appliquent généralement des limites avec des fenêtres glissantes ou des contrôles de type token bucket. Une courte rafale peut épuiser la capacité immédiatement disponible même si le calcul pour la minute entière semble sûr.

D’autres raisons peuvent expliquer l’apparition précoce d’un 429 :

  • La limite s’applique à un projet, une organisation, un compte, une famille de modèles ou un niveau de service plutôt qu’à une seule clé API.
  • Les jetons d’entrée et de sortie utilisent des compartiments séparés.
  • Plusieurs workers, services ou utilisateurs partagent le même pool de quota.
  • Les tentatives de réessai provenant d’échecs précédents consomment la même limite.
  • Le fournisseur applique une limite d’accélération ou de rafale pendant que le trafic augmente fortement.
  • Un pool spécifique à un modèle est saturé alors qu’un autre modèle dispose encore de capacité.

C’est pourquoi l’application ne doit pas déduire la cause à partir de son seul compteur de requêtes. Lisez le corps de la réponse et les en-têtes, conservez les identifiants de requête du fournisseur et consignez le modèle, le compte, les estimations de jetons, le numéro de tentative et le délai dans la file d’attente.

Une formule pratique de planification de capacité

Commencez avec deux plafonds indépendants.

request_ceiling = RPM × safety_factor

token_ceiling = (TPM × safety_factor) ÷ average_tokens_per_request

safe_requests_per_minute = min(request_ceiling, token_ceiling)

Utilisez un facteur de sécurité inférieur à 1.0 — par exemple 0.7 à 0.9 — pour absorber la variabilité des tokens, les tentatives de réessai, les consommateurs partagés et les arrivées irrégulières.

Exemple

Supposons qu’un pool de modèles autorise :

  • 1 000 RPM
  • 2 000 000 TPM
  • 4 000 tokens totaux moyens par requête
  • Facteur de sécurité opérationnel de 80 %
request_ceiling = 1,000 × 0.8 = 800 requests/minute

token_ceiling = (2,000,000 × 0.8) ÷ 4,000
              = 400 requests/minute

safe_requests_per_minute = min(800, 400) = 400

Le TPM est la contrainte limitante. Ajouter davantage de workers n’augmentera pas le débit durable ; cela créera seulement une file d’attente plus importante ou davantage de réponses 429.

Pour les systèmes en ligne, traduisez le débit en point de départ de concurrence avec la loi de Little :

target_concurrency ≈ requests_per_second × average_request_seconds

Si le taux sûr est de 400 requêtes par minute (6,67 par seconde) et que la latence moyenne du modèle est de 3 secondes, une concurrence de départ est d’environ 20. Ajoutez de la marge avec prudence, puis ajustez en fonction de la latence p95 réelle et des distributions de tokens.

Les limites de tokens sont souvent le goulot d’étranglement caché

Les équipes surveillent fréquemment le nombre de requêtes mais négligent le volume de tokens. La pression sur le TPM augmente lorsque vous :

  • Ajoutez davantage de documents récupérés à chaque prompt.
  • Conservez de longs historiques de conversation.
  • Exécutez plusieurs complétions candidates par tâche.
  • Augmentez les plafonds de sortie.
  • Envoyez à plusieurs reprises le même grand prompt système.
  • Lancez des suites d’évaluation parallèles sur le quota d’un même projet.

Mesurez au moins quatre valeurs de tokens par requête réussie :

  1. Tokens d’entrée.
  2. Tokens de sortie.
  3. Tokens totaux.
  4. Un p50, p95 et un maximum glissants par charge de travail et par modèle.

La planification de capacité basée uniquement sur la moyenne est optimiste. Un planificateur plus sûr réserve en fonction d’un percentile élevé ou d’une estimation spécifique à la charge de travail, puis rapproche la réservation de l’utilisation réelle après l’achèvement.

Ce que signifie un 429 — et ce qu’il ne signifie pas

HTTP 429 Too Many Requests vous indique que le serveur a rejeté la requête en vertu d’une limite active ou d’une politique de capacité. Cela ne signifie pas automatiquement « dormir une seconde et réessayer ».

Classez un 429 dans une catégorie opérationnelle :

Classe 429 Indices Action correcte
Courte rafale Pic récent ; l’en-tête de réessai est court ; la file d’attente est par ailleurs saine Attendez l’indication du serveur, puis réessayez avec du jitter
Épuisement soutenu du RPM Le taux de requêtes reste proche du plafond Échelonnez ou mettez en file d’attente ; les réessais seuls ne peuvent pas corriger cela
Épuisement soutenu du TPM Le taux de jetons est élevé ; les prompts longs ou les sorties dominent Réduisez les jetons, retardez le travail ou routez vers un autre pool éligible
Limite quotidienne ou de palier L’erreur identifie un quota quotidien, la facturation ou une restriction de palier Arrêtez les réessais ; reprogrammez ou modifiez la capacité du compte
Limite d’accélération Le trafic a augmenté rapidement à partir d’une base faible Augmentez progressivement et lissez les rafales
Événement de capacité du fournisseur Taux client normal mais rejet transitoire répété Utilisez un petit budget de réessais, puis un repli sûr contractuellement

Le corps et les en-têtes diffèrent selon le fournisseur. Préférez un Retry-After explicite ou un signal de réinitialisation de limite de débit lorsqu’il est fourni. Sinon, utilisez un backoff exponentiel avec un jitter aléatoire.

Backoff exponentiel avec jitter

Le backoff exponentiel augmente le délai après chaque tentative échouée. Le jitter randomise ce délai afin que des centaines de workers ne réessaient pas au même instant.

Une formule courante de full-jitter est :

delay_ms = random(0, min(cap_ms, base_ms × 2^attempt))

Une politique de réessai en production a également besoin de limites :

  • Nombre maximal de tentatives : généralement un petit nombre, pas une boucle infinie.
  • Temps écoulé maximal : arrêter lorsque le budget de latence de l’appelant est épuisé.
  • Liste des statuts réessayables : généralement 429, certaines réponses 5xx sélectionnées et les échecs réseau sûrs.
  • Indices du serveur : respecter Retry-After lorsqu’il est valide.
  • Annulation : arrêter immédiatement lorsque la requête amont est interrompue.
  • Observabilité : enregistrer le nombre de tentatives, le temps d’attente, le statut final et l’ID de requête du fournisseur.

Les requêtes infructueuses peuvent tout de même consommer de la capacité de limite de débit. Des réessais agressifs peuvent donc prolonger la période de limitation.

TypeScript : un assistant de réessai borné

L’exemple suivant utilise l’URL de base Flatkey compatible avec OpenAI. Il ne réessaie qu’avant qu’un corps de réponse réussi soit consommé et s’arrête lorsque la limite de tentatives ou le budget de temps total est épuisé.

type ChatRequest = {
  model: string;
  messages: Array<{ role: "system" | "user" | "assistant"; content: string }>;
  max_tokens?: number;
};

const sleep = (milliseconds: number) =>
  new Promise((resolve) => setTimeout(resolve, milliseconds));

function retryAfterMilliseconds(response: Response): number | null {
  const value = response.headers.get("retry-after");
  if (!value) return null;

  const seconds = Number(value);
  if (Number.isFinite(seconds)) return Math.max(0, seconds * 1_000);

  const date = Date.parse(value);
  return Number.isNaN(date) ? null : Math.max(0, date - Date.now());
}

export async function createChatCompletion(
  apiKey: string,
  request: ChatRequest,
  options: { maxAttempts?: number; maxElapsedMs?: number } = {},
) {
  const maxAttempts = options.maxAttempts ?? 4;
  const maxElapsedMs = options.maxElapsedMs ?? 30_000;
  const startedAt = Date.now();

  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
    const response = await fetch(
      "https://router.flatkey.ai/v1/chat/completions",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(request),
      },
    );

    if (response.ok) return response.json();

    const retryable = response.status === 429 || response.status >= 500;
    const finalAttempt = attempt === maxAttempts - 1;
    if (!retryable || finalAttempt) {
      throw new Error(`La requête LLM a échoué avec ${response.status} : ${await response.text()}`);
    }

    const hintedDelay = retryAfterMilliseconds(response);
    const exponentialCap = Math.min(8_000, 500 * 2 ** attempt);
    const jitteredDelay = Math.random() * exponentialCap;
    const delayMs = hintedDelay ?? jitteredDelay;

    if (Date.now() + delayMs - startedAt >= maxElapsedMs) {
      throw new Error("Budget de réessai LLM épuisé");
    }

    await sleep(delayMs);
  }

  throw new Error("État de réessai inatteignable");
}

Pour une utilisation en production, ajoutez des délais d’attente de requête, des types d’erreur structurés, des métriques et le signal d’annulation de votre application. Si l’opération peut créer des effets de bord externes — comme envoyer un e-mail ou exécuter un outil — rendez l’opération métier idempotente avant de la réessayer.

Réessayer, mettre en file d’attente, réduire ou rediriger ?

Utilisez la cause, et non le seul code de statut, pour choisir le contrôle.

Situation Réessayer Mettre en file d’attente Réduire les jetons Routage ailleurs
Un seul 429 transitoire isolé Oui, borné Optionnel Non En général non
Épuisement répété du RPM Limité Oui Non Parfois
Épuisement répété du TPM Limité Oui Oui Souvent utile
Quota quotidien épuisé Non Pour plus tard Optionnel Oui, si la politique le permet
Incident 5xx du fournisseur Oui, borné Oui Non Oui après le budget de tentatives
Réponse de streaming partielle Pas de relecture automatique Spécifique à l’application Non Uniquement avec une sémantique de récupération explicite

Réessayer

Réessayez lorsque l’échec est transitoire et que l’appelant dispose encore de temps. Conservez un budget de tentatives par requête et un budget de tentatives au niveau du service afin qu’un incident chez le fournisseur ne puisse pas multiplier le trafic total.

Mettre en file d’attente

Mettez en file d’attente lorsque le taux d’arrivée dépasse temporairement le taux de service soutenable. Une file d’attente utile expose :

  • L’âge de l’élément le plus ancien.
  • L’heure de début estimée.
  • L’équité par tenant.
  • L’annulation des tâches obsolètes.
  • Une profondeur maximale avec un comportement explicite d’abandon.

Réduire les jetons

Lorsque le TPM est contraint, supprimez le contexte non pertinent, résumez l’historique, réduisez le nombre de candidats, abaissez les limites de sortie, mettez en cache les préfixes de prompt réutilisables lorsque c’est pris en charge, et séparez le trafic interactif court des longues tâches par lot.

Routage ailleurs

Le routage est approprié lorsqu’un autre modèle ou fournisseur répond au même contrat et dispose d’une capacité saine. Le mécanisme de repli doit préserver les capacités requises telles que la sortie structurée, l’appel d’outils, la longueur de contexte, la politique de sécurité et l’objectif de latence. Pour un cadre d’implémentation plus approfondi, utilisez le playbook de routage de repli pour les API LLM.

Limites de débit dans les évaluations de modèles

Un mauvais contrôle de débit peut invalider une évaluation.

Supposons que le modèle A soit testé avec 10 travailleurs tandis que le modèle B est testé avec 100. Si le modèle B passe plus de temps limité par le débit, sa latence mesurée inclut la mise en file d’attente et le délai de réessai, que le modèle A n’a jamais subis. Le résultat peut décrire la configuration de votre banc d’essai plutôt que les performances du modèle.

Pour des comparaisons défendables :

  1. Séparez la latence du modèle, le délai de file d’attente et le délai de réessai.
  2. Appliquez le même processus d’arrivée ou le même niveau d’utilisation normalisé à chaque fournisseur.
  3. Réchauffez le trafic progressivement lorsque les fournisseurs utilisent des contrôles d’accélération.
  4. Enregistrez les jetons et les tentatives par tâche terminée.
  5. Indiquez à la fois le taux de réussite au premier essai et le taux de réussite final.
  6. Comparez le coût par tâche acceptée, et pas seulement le coût par jeton.
  7. Exécutez les tests de surcharge séparément des benchmarks de qualité et de latence.

Si vous évaluez les fournisseurs à la fois sur la fiabilité et le coût, associez ce processus à la comparaison des tarifs des API IA.

Une architecture de limitation de débit en production

Un chemin de requête robuste comporte généralement cinq couches de contrôle :

  1. Contrôle d’admission rejette ou diffère le travail qui ne peut pas respecter son délai.
  2. Réservation de jetons estime le coût probable de quota de la requête.
  3. Limiteur de débit cadence chaque fournisseur, pool de modèles, locataire et classe de priorité.
  4. Contrôleur de réessai dépense un budget de réessais borné avec jitter.
  5. Routeur sélectionne une alternative compatible avec le contrat après que le budget de réessai ou la politique de capacité indique qu’il faut basculer.
client
  → contrôle d’admission
  → file de priorité
  → limiteur RPM + réservation de jetons
  → route fournisseur/modèle
  → réessai borné
  → solution de repli sûre vis-à-vis du contrat
  → journaux d’utilisation et de latence

N’intégrez pas une boucle de réessai illimitée dans chaque worker applicatif. Centralisez la politique afin que tous les appelants partagent la même compréhension de la capacité disponible.

Métriques qui valent la peine d’être surveillées

Suivez-les par fournisseur, modèle, projet, route, locataire et charge de travail :

  • Requêtes par minute et jetons par minute.
  • Jetons estimés réservés par rapport aux jetons réellement utilisés.
  • Taux de réussite au premier essai.
  • Tentatives de réessai par requête réussie.
  • Taux de 429 par cause classifiée.
  • Profondeur de la file et ancienneté de l’élément le plus ancien.
  • Temps passé à attendre de la capacité de débit.
  • Latence de bout en bout p50, p95 et p99.
  • Taux de solution de repli et résultat du repli.
  • Coût par tâche réussie ou acceptée.

Une alerte basée uniquement sur le nombre total de 429 est bruyante. Un meilleur signal combine le taux de limitation avec l’âge de la file, l’amplification des réessais et le taux d’échec final.

Erreurs courantes

Considérer le RPM comme une limite de concurrence

Le RPM mesure les admissions dans le temps ; la concurrence mesure le travail en cours. Des requêtes lentes peuvent créer une forte concurrence avec un RPM modeste.

Réessayer immédiatement chaque 429

Les réessais immédiats synchronisent les workers et consomment davantage de capacité. Respectez le timing du serveur lorsqu’il est disponible et ajoutez du jitter.

Utiliser un seul limiteur pour tous les modèles

Les fournisseurs peuvent utiliser des pools distincts ou partagés. La politique spécifique au modèle doit suivre le périmètre de quota documenté par le fournisseur et les en-têtes observés.

Ignorer les consommateurs partagés

Un tableau de bord, un job batch et une API de production peuvent partager un même quota de projet. Réservez la capacité par charge de travail et isolez le trafic critique lorsque c’est possible.

Réessayer un flux partiel

Une fois que des jetons ont atteint l’utilisateur, rejouer la requête peut dupliquer du contenu ou des actions d’outil. Définissez des sémantiques explicites de continuation ou de redémarrage au lieu de réessayer silencieusement.

Comment Flatkey modifie le modèle opérationnel

Flatkey fournit une clé API et une URL de base compatible avec OpenAI pour accéder aux fournisseurs de modèles pris en charge. Cela offre à une application une seule surface d’intégration tout en permettant à la politique de routage de prendre en compte l’adéquation du modèle, la capacité, la fiabilité et le coût.

La passerelle ne supprime pas les limites en amont. Elle facilite la mise en place de contrôles cohérents autour d’elles : une seule intégration client, des journaux de requêtes centralisés et la possibilité de déplacer le trafic éligible lorsqu’une route est contrainte. Consultez le guide d’architecture de passerelle d’API IA pour une vue plus large de la conception du routage, ou voyez le tarif actuel de Flatkey avant de sélectionner les routes de production.

FAQ

Quelle est la différence entre RPM et TPM ?

Le RPM limite le nombre de requêtes admises dans le temps. Le TPM limite le nombre de jetons d’entrée et/ou de sortie admis. Les prompts courts exercent généralement d’abord une pression sur le RPM ; les charges de travail à grand contexte ou à forte génération exercent souvent d’abord une pression sur le TPM.

Pourquoi est-ce que j’obtiens des erreurs 429 en dessous de ma limite RPM ?

Le fournisseur peut appliquer des fenêtres glissantes plus courtes, des token buckets, des quotas de projet partagés, des limites de jetons séparées, des limites d’accélération ou des pools spécifiques au modèle. Votre compteur local de requêtes peut ne pas représenter l’ensemble du périmètre du quota.

Dois-je réessayer chaque 429 ?

Non. Réessayez les limitations temporaires avec un petit budget et du jitter. Ne réessayez pas de façon répétée en cas d’épuisement du quota quotidien, de restrictions de facturation ou de surcharge soutenue qui n’a pas le temps de se résorber.

Le backoff exponentiel garantit-il le succès ?

Non. Le backoff réduit les collisions et donne à la capacité transitoire le temps de se rétablir. Il ne peut pas créer de quota. Un épuisement persistant nécessite une demande plus faible, plus de capacité, un travail différé ou une autre route éligible.

Combien de tentatives une requête LLM doit-elle utiliser ?

Il n’existe pas de nombre universel. Définissez les tentatives en fonction du budget de latence visible pour l’utilisateur et du mode d’échec. De nombreuses applications interactives ne devraient autoriser que quelques tentatives courtes avant d’échouer ou d’emprunter une autre route ; les tâches hors ligne peuvent tolérer des files d’attente plus longues.

Les tentatives de réessai comptent-elles dans les limites de débit ?

Elles le peuvent. Les fournisseurs peuvent compter les tentatives infructueuses dans les limites actives, de sorte que l’amplification des réessais doit être surveillée et bornée.

Liste de vérification finale

  • Modélisez séparément le RPM, le TPM, les limites quotidiennes et la concurrence.
  • Calculez la capacité à partir du minimum des plafonds de requêtes et de jetons.
  • Opérez en dessous du maximum publié avec une marge de sécurité.
  • Utilisez des files d’attente et un étalement temporel pour une charge soutenue.
  • Respectez Retry-After et utilisez un backoff exponentiel avec jitter.
  • Limitez le nombre de tentatives et le temps total de réessai.
  • Ne rejouez pas automatiquement les flux partiels ni les effets de bord.
  • Orientez uniquement vers des modèles qui préservent le contrat requis.
  • Séparez la file d’attente et le délai de réessai de la latence du modèle dans les évaluations.
  • Alertez sur l’amplification des réessais et l’âge de la file, pas seulement sur les décomptes bruts de 429.

Les limites de débit relèvent d’abord d’un problème de planification de capacité, avant d’être un problème de réessai. Une fois que vous mesurez indépendamment la fréquence des requêtes, le débit de jetons, la concurrence et l’amplification des réessais, les erreurs 429 deviennent des signaux exploitables au lieu d’un bruit de production imprévisible.