Aller au contenu principal

Quand utiliser async vs sync

Le choix n’est pas toujours evident

L’asynchrone n’est pas systematiquement superieur au synchrone. Chaque approche a ses contextes ou elle excelle, et choisir la mauvaise peut compliquer votre code sans gain de performance. Cette lecon vous aide a determiner quelle approche adopter selon votre situation.

Quand le synchrone suffit

Le client synchrone est le bon choix dans plusieurs scenarios courants :

  • Script ponctuel : vous envoyez quelques requetes dans un script de test ou d’exploration. La simplicite du code prime.
  • Pipeline sequentiel : chaque requete depend du resultat de la precedente. Le parallelisme n’apporte rien.
  • Application Django traditionnelle : si votre stack n’est pas asynchrone, ajouter asyncio uniquement pour les appels API cree de la complexite inutile.
  • Prototypage rapide : quand vous testez un prompt ou validez un concept, le code synchrone est plus lisible et plus rapide a ecrire.
# Synchrone — parfait pour un pipeline sequentiel
from openai import OpenAI

client = OpenAI(api_key=os.getenv("XAI_API_KEY"), base_url="https://api.x.ai/v1")

# Etape 1 : analyser le texte
analysis = client.chat.completions.create(
    model="grok-4",
    messages=[{"role": "user", "content": f"Analyse ce texte : {text}"}]
).choices[0].message.content

# Etape 2 : generer un resume base sur l'analyse
summary = client.chat.completions.create(
    model="grok-4",
    messages=[{"role": "user", "content": f"Resume selon cette analyse : {analysis}"}]
).choices[0].message.content

Dans cet exemple, l’etape 2 a besoin du resultat de l’etape 1. L’asynchrone ne gagnerait rien.

Quand l’asynchrone est necessaire

Passez en asynchrone dans ces situations :

  • Traitement par lots : vous envoyez des dizaines ou centaines de requetes independantes. Le gain de temps est proportionnel au nombre de requetes.
  • Application web FastAPI/Starlette : votre framework est deja asynchrone. Utiliser un client synchrone bloquerait l’event loop.
  • Chatbot avec plusieurs sources : vous interrogez Grok, une base de donnees et une API externe en parallele pour construire une reponse.
  • Monitoring en temps reel : vous surveillez plusieurs flux simultanement.
# Asynchrone — traitement de 50 questions en parallele
async def batch_process(questions: list[str]) -> list[str]:
    sem = asyncio.Semaphore(5)

    async def ask(q: str) -> str:
        async with sem:
            resp = await client.chat.completions.create(
                model="grok-4",
                messages=[{"role": "user", "content": q}]
            )
            return resp.choices[0].message.content

    return await asyncio.gather(*[ask(q) for q in questions])

Avec 50 questions et un semaphore de 5, vous traitez 5 requetes en parallele au lieu d’une seule. Si chaque requete prend 8 secondes, le temps total passe de 400 secondes a environ 80 secondes.

Le piege de l’asynchrone premature

Un code asynchrone mal concu est pire qu’un code synchrone bien ecrit. Voici les erreurs courantes :

Bloquer l’event loop

# MAUVAIS : appel synchrone dans une fonction async
async def bad_example():
    response = requests.get("https://api.example.com")  # bloque tout
    return response.json()

La bibliotheque requests est synchrone. L’appeler dans une coroutine bloque l’event loop et annule tout benefice de l’asynchrone. Utilisez httpx ou aiohttp a la place.

Complexite inutile

# MAUVAIS : async pour une seule requete
async def over_engineered():
    response = await client.chat.completions.create(...)
    return response

# Equivalent synchrone, plus simple
def simple():
    response = client.chat.completions.create(...)
    return response

Si vous n’avez qu’une seule requete a envoyer, l’asynchrone ajoute de la complexite sans benefice.

Arbre de decision

Pour choisir entre sync et async, posez-vous ces questions dans l’ordre :

  1. Combien de requetes API envoyez-vous ? Si une seule ou quelques-unes en sequence, restez en synchrone.
  2. Les requetes sont-elles independantes ? Si chaque requete depend de la precedente, restez en synchrone.
  3. Votre framework est-il asynchrone ? Si oui (FastAPI, Starlette, aiohttp), utilisez l’asynchrone pour ne pas bloquer l’event loop.
  4. Le temps de traitement total est-il un probleme ? Si vous traitez des lots et que le temps synchrone est inacceptable, passez en asynchrone.

Points cles a retenir

  • Le synchrone convient aux scripts simples, pipelines sequentiels et prototypage
  • L’asynchrone est necessaire pour le traitement par lots, les frameworks async et les requetes paralleles
  • Ne jamais utiliser de bibliotheques synchrones (requests) dans du code asynchrone
  • La complexite ajoutee par l’asynchrone doit etre justifiee par un gain mesurable
  • Commencez en synchrone, migrez en asynchrone quand le besoin se confirme