
Timeout d'API IA : causes, stratégies de retry et architecture de fallback

Votre requête API IA a expiré. Mais « timeout » n'est pas un seul problème — c'est au moins quatre problèmes différents qui se cachent derrière le même message d'erreur.
Un modèle texte qui expire après 30 secondes est un problème différent d'un job de génération vidéo qui expire après 5 minutes. Corriger le mauvais type fait perdre du temps d'ingénierie et peut aggraver le problème.
Ce guide vous aide à diagnostiquer le type de timeout auquel vous faites face et à choisir le bon schéma de réponse.
En bref
- Les timeouts d'API IA ont des causes racines différentes : latence du modèle, file d'attente du fournisseur, entrée volumineuse ou problèmes réseau.
- Les timeouts de modèles texte et ceux de génération vidéo/image nécessitent des stratégies de traitement différentes.
- Ne pas réessayer aveuglément — certains timeouts signifient que la requête est encore en cours de traitement.
- Pour les tâches longues (vidéo, image), utilisez des patterns asynchrones plutôt que d'attendre des réponses synchrones.
- Concevez le fallback avant d'en avoir besoin : un timeout plus court avec un modèle de secours est souvent préférable à un timeout long sans fallback.
Tableau de diagnostic des timeouts
Utilisez ce tableau pour identifier votre type de timeout avant de choisir une solution :
| Type de timeout | Durée typique | Cause racine | Comment vérifier | Bonne réponse |
|---|---|---|---|---|
| Modèle texte — réponse lente | 15–60 s | Entrée volumineuse, raisonnement complexe ou nombre élevé de tokens en sortie | Vérifier la taille de l'entrée et max_tokens | Réduire l'entrée, baisser max_tokens ou passer à un modèle plus rapide |
| Modèle texte — fournisseur surchargé | 30–120 s | Fournisseur sous forte charge ; requêtes en file d'attente | Tester la même requête en heures creuses | Réessayer avec backoff ou router vers un autre fournisseur |
| Génération vidéo/image — traitement normal | 60–300 s+ | La génération prend du temps par conception (surtout la vidéo) | Consulter la documentation du fournisseur pour les temps de génération attendus | Utiliser le polling asynchrone, pas l'attente synchrone |
| Génération vidéo/image — engorgement de la file | 300 s+ | Trop de jobs en attente dans la file du fournisseur | Vérifier le statut ou la position dans la file du fournisseur | Ajouter une gestion de file, définir les attentes utilisateur ou utiliser un autre fournisseur |
| Timeout réseau | Variable | DNS, pare-feu, proxy ou problèmes de connectivité | Tester avec une simple requête de health-check | Corriger la configuration réseau, pas l'appel API |
| Timeout côté client trop court | Fixé par configuration | Le timeout de votre client HTTP est plus court que ce dont le modèle a besoin | Augmenter le paramètre de timeout et retester | Ajuster le timeout client au temps de réponse attendu |
Pattern 1 : Gestion des timeouts de modèles texte
Les timeouts de modèles texte sont généralement causés par l'une de ces trois choses :
1.1 Entrée volumineuse ou max_tokens élevé
max_tokens permettent une génération plus longue, qui prend plus de temps.# Problème : entrée volumineuse + max_tokens élevé = réponse lente
response = client.chat.completions.create(
model="gpt-4o",
messages=very_long_messages, # 100K+ tokens
max_tokens=4096 # Sortie longue demandée
)
# Solution : réduire l'entrée ou limiter la sortie
response = client.chat.completions.create(
model="gpt-4o",
messages=trimmed_messages, # Réduit à 50K tokens
max_tokens=1024 # Sortie plus courte
)1.2 Fournisseur sous charge
Pendant les pics d'utilisation, les fournisseurs peuvent mettre votre requête en file d'attente. Cela se manifeste par un timeout plutôt qu'un message de file d'attente explicite.
- La même requête fonctionne bien en heures creuses
- L'erreur est intermittente, pas systématique
- D'autres utilisateurs signalent des problèmes similaires au même moment
- Réessayer avec un backoff aléatoire (jitter)
- Router vers un fournisseur ou modèle alternatif
- Utiliser le streaming pour obtenir des résultats partiels plus rapidement
1.3 Le streaming comme atténuation des timeouts
Le streaming n'accélère pas la génération, mais il commence à renvoyer des tokens plus tôt. Cela peut empêcher le déclenchement des timeouts côté client :
# Synchrone — le client peut expirer en attendant la réponse complète
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
max_tokens=2048
)
# Streaming — le premier token arrive plus vite, maintient la connexion active
stream = client.chat.completions.create(
model="gpt-4o",
messages=messages,
max_tokens=2048,
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")Pattern 2 : Gestion des timeouts de génération vidéo/image
La génération vidéo et image est fondamentalement différente du texte. Des temps de génération de 30 secondes à plusieurs minutes sont normaux, pas des erreurs.
2.1 Génération synchrone vs asynchrone
| Approche | Fonctionnement | Quand l'utiliser |
|---|---|---|
| Synchrone | Attendre la réponse complète en un seul appel HTTP | Générations rapides (< 30 s), intégrations simples |
| Polling asynchrone | Soumettre le job → obtenir l'ID → interroger le statut → récupérer le résultat | Génération vidéo, traitement par lots, toute tâche > 30 s |
| Webhooks | Soumettre le job → le fournisseur appelle votre endpoint quand c'est terminé | Pipelines à haut volume, architectures événementielles |
2.2 Pattern de polling asynchrone
import asyncio
import httpx
async def generate_video_async(client, prompt: str, timeout: int = 600):
"""Soumettre un job de génération vidéo et interroger jusqu'à complétion."""
# Étape 1 : Soumettre le job
submit_response = await client.post(
"/v1/video/generations",
json={"model": "veo-3-fast", "prompt": prompt}
)
job_id = submit_response.json()["id"]
# Étape 2 : Interroger jusqu'à complétion
for _ in range(timeout // 5): # Vérifier toutes les 5 secondes
status_response = await client.get(f"/v1/video/generations/{job_id}")
status = status_response.json()
if status["status"] == "completed":
return status["result"]
elif status["status"] == "failed":
raise RuntimeError(f"Generation failed: {status.get('error')}")
await asyncio.sleep(5)
raise TimeoutError(f"Video generation did not complete within {timeout}s")2.3 Connaissance de la position en file d'attente
Quand un fournisseur de génération vidéo a un retard accumulé, votre job attend dans la file avant que le traitement ne commence. Certains fournisseurs exposent la position dans la file :
Status: queued → position 42
Status: queued → position 15
Status: processing → estimated 90s remaining
Status: completed → download URL availableSi le fournisseur n'expose pas la position dans la file, estimez à partir des temps d'attente historiques et définissez les attentes utilisateur en conséquence.
Pattern 3 : Logique de retry intelligente pour les timeouts
Tous les timeouts ne doivent pas être réessayés de la même manière :
import asyncio
import random
async def retry_with_timeout_awareness(
make_request,
max_retries: int = 3,
base_timeout: float = 30.0
):
"""Retry avec prise en compte du type de timeout."""
for attempt in range(max_retries):
try:
return await asyncio.wait_for(
make_request(),
timeout=base_timeout * (1.5 ** attempt) # Augmenter le timeout à chaque retry
)
except asyncio.TimeoutError:
if attempt == max_retries - 1:
raise
# Ajouter du jitter pour éviter l'effet thundering herd
delay = min(30, (2 ** attempt) + random.uniform(0, 1))
await asyncio.sleep(delay)
except Exception as e:
# Erreurs non-timeout : ne pas réessayer automatiquement
if "429" in str(e):
delay = min(60, (2 ** attempt) + random.uniform(0, 2))
await asyncio.sleep(delay)
else:
raiseRègles de retry selon le type de timeout
| Type de timeout | Faut-il réessayer ? | Comment |
|---|---|---|
| Modèle texte lent | Oui | Réessayer avec backoff ; envisager un modèle plus rapide au retry |
| Fournisseur surchargé | Oui, avec prudence | Réessayer avec un backoff plus long ; envisager un autre fournisseur |
| Génération vidéo encore en cours | Non — le job peut encore tourner | Interroger le statut au lieu de resoumettre |
| Timeout réseau | Oui | Corriger le réseau d'abord ; réessayer après confirmation de la connectivité |
| Timeout client trop court | Non — augmenter le timeout à la place | Ajuster la configuration, ne pas réessayer |
L'erreur la plus dangereuse est de réessayer un job de génération vidéo qui est encore en cours de traitement. Cela crée des jobs en double, gaspille de l'argent et peut surcharger la file d'attente du fournisseur.
Pattern 4 : Architecture de fallback pour la production
Fallback de modèle déclenché par timeout
async def call_with_fallback(messages, client, primary_model, fallback_model):
"""Essayer le modèle principal ; en cas de timeout, basculer sur un modèle plus rapide."""
try:
return await asyncio.wait_for(
client.chat.completions.create(
model=primary_model,
messages=messages
),
timeout=30.0
)
except asyncio.TimeoutError:
# Basculer sur un modèle plus rapide, éventuellement plus petit
return await client.chat.completions.create(
model=fallback_model,
messages=messages
)Utiliser une passerelle de routage pour la résilience aux timeouts
Au lieu d'implémenter la logique de fallback dans chaque service, une passerelle de routage peut gérer les timeouts au niveau de l'infrastructure :
- Router vers des fournisseurs plus rapides quand les routes principales sont lentes
- Réessayer automatiquement via un chemin upstream différent
- Renvoyer le modèle réellement utilisé pour que votre application sache ce qui s'est passé
from openai import OpenAI
client = OpenAI(
api_key="your-evolink-key",
base_url="https://api.evolink.ai/v1"
)
# Smart Router gère la sélection du fournisseur et le fallback
response = client.chat.completions.create(
model="evolink/auto",
messages=messages
)Référence de configuration des timeouts
| Paramètre | Valeur recommandée | Pourquoi |
|---|---|---|
| Timeout client HTTP (texte) | 60–120 s | Permettre les entrées volumineuses et le raisonnement complexe |
| Timeout client HTTP (image) | 120–300 s | La génération d'image varie selon le modèle et la résolution |
| Timeout client HTTP (vidéo) | Utiliser le polling asynchrone | Le timeout synchrone n'est pas adapté à la vidéo |
| Tentatives de retry | 2–3 pour le texte, 0 pour les vidéos en cours | Éviter les jobs vidéo/image en double |
| Délai de base du backoff | 2 s avec jitter | Prévenir l'effet thundering herd lors de la reprise du fournisseur |
| Timeout de bascule vers le modèle de secours | 15–30 s | Basculer vers un modèle plus rapide avant la frustration de l'utilisateur |
Articles connexes
- Fix OpenRouter 429 "Provider Returned Error" — quand l'erreur est du rate limiting, pas un timeout
- Context Length Exceeded in LLM API Calls — quand une entrée volumineuse provoque un rejet plutôt qu'un timeout
- How to Reduce 429 Errors in Agent Workloads — gérer le trafic en rafale qui mène aux timeouts
- Best AI API Platform for Production Reliability — choisir une plateforme avec failover intégré
FAQ
Pourquoi ma requête API IA expire-t-elle alors que le modèle fonctionne ?
Les timeouts sont généralement causés par l'un des facteurs suivants : (1) une entrée volumineuse qui prend plus de temps à traiter, (2) un fournisseur sous forte charge, (3) un timeout côté client configuré trop court, ou (4) des problèmes réseau. Le modèle lui-même peut fonctionner parfaitement.
Dois-je augmenter mon timeout ou adopter une approche différente ?
Cela dépend. Pour les modèles texte, augmenter le timeout aide avec les réponses occasionnellement lentes. Pour la génération vidéo/image, passez au polling asynchrone plutôt que d'augmenter le timeout synchrone. Pour les timeouts persistants, investiguez la cause racine avant d'augmenter les limites.
Un timeout est-il la même chose qu'une erreur de rate limit ?
Non. Un timeout signifie que le serveur n'a pas répondu dans votre limite de temps. Un rate limit (429) signifie que le serveur a activement rejeté votre requête. Les timeouts indiquent souvent un traitement lent ; les 429 indiquent trop de requêtes.
Comment gérer les timeouts en génération vidéo ?
N'attendez jamais de manière synchrone la génération vidéo. Utilisez la soumission asynchrone de jobs avec polling ou webhooks. Si un job vidéo expire pendant le polling, vérifiez son statut avant de le resoumettre — le job peut encore être en cours de traitement.
Le streaming peut-il prévenir les timeouts ?
Le streaming prévient les timeouts côté client car le premier token arrive rapidement, maintenant la connexion active. Cependant, le streaming ne rend pas la génération totale plus rapide — il change simplement le mode de livraison.
Quand dois-je basculer vers un modèle de secours en cas de timeout ?
Définissez un seuil (par exemple, 15–30 secondes pour le texte) et basculez vers un modèle plus rapide quand le modèle principal expire. Cela donne aux utilisateurs une réponse plutôt qu'une erreur. Le modèle de secours peut être moins performant, mais une réponse légèrement moins bonne vaut mieux qu'aucune réponse.

