Aller au contenu principal

Limitations de la plateforme

Mis à jour le 29 juillet 2026

Connaître les limites

La plateforme Workflows de Mistral est en Public Preview (avril 2026). Comme tout système d’orchestration, elle impose des limitations techniques qu’il est essentiel de connaître pour concevoir des workflows robustes. Ces limites ne sont pas des détails de documentation : elles se manifestent en production, souvent tard, sous la forme d’erreurs de sérialisation ou de workflows terminés de force que rien dans votre code ne laissait présager. Les connaître à l’avance change la façon dont vous découpez vos traitements.

Le tableau ci-dessous rassemble l’essentiel, avec pour chaque limite la conséquence concrète d’un dépassement.

Limitation Valeur Conséquence si dépassée
Délai entre activités 2 secondes Latence incompressible entre chaque appel d'activité
Input/output par invocation 2 MB Erreur de sérialisation, workflow échoue
Événements par exécution 51 200 Workflow terminé de force
Taille totale par exécution 50 MB Workflow terminé de force
Timeout par défaut 1 heure Workflow annulé (configurable jusqu'à 7 jours)
Timeout maximum 7 jours Workflow annulé automatiquement
I/O dans les workflows Interdit Erreur de non-déterminisme lors du replay

Deux secondes entre chaque activité

La plateforme impose un délai minimum de 2 secondes entre deux appels d’activité. Cette latence n’est pas un défaut de jeunesse : elle est inhérente à l’architecture d’orchestration, qui persiste chaque événement avant de poursuivre. C’est le prix de la durabilité.

L’impact est facile à calculer et surprend souvent. Un workflow qui enchaîne dix activités séquentielles consomme au minimum vingt secondes d’orchestration, indépendamment du temps que prennent les activités elles-mêmes. Si chacune s’exécute en cinquante millisecondes, vous avez conçu un traitement d’une demi-seconde qui met vingt secondes à rendre son résultat.

La parade consiste à regrouper dans une seule activité les opérations qui n’ont pas besoin d’être séparées. Comparez ces deux versions d’un même pipeline NLP.

# SOUS-OPTIMAL : 3 activités = 6 secondes de latence d'orchestration
@workflows.workflow.define(name="pipeline_lent")
class PipelineLent:
    @workflows.workflow.entrypoint
    async def run(self, texte: str) -> dict:
        tokens = await tokeniser(texte)
        embeddings = await calculer_embeddings(tokens)
        clusters = await clusteriser(embeddings)
        return clusters

# OPTIMISÉ : 1 activité = 2 secondes de latence d'orchestration
@workflows.activity()
async def traitement_nlp_complet(texte: str) -> dict:
    tokens = tokeniser_local(texte)
    embeddings = calculer_embeddings_local(tokens)
    clusters = clusteriser_local(embeddings)
    return {"clusters": clusters}

@workflows.workflow.define(name="pipeline_rapide")
class PipelineRapide:
    @workflows.workflow.entrypoint
    async def run(self, texte: str) -> dict:
        return await traitement_nlp_complet(texte)

Le critère de découpage devient alors simple à énoncer : ne créez une activité séparée que si vous avez besoin de la garantie de persistance entre deux opérations. Si deux opérations peuvent échouer ensemble sans que cela pose problème — ici, une tokenisation locale et un calcul d’embeddings enchaînés en mémoire — regroupez-les.

Deux mégaoctets par invocation

Chaque appel d’activité est limité à 2 MB en entrée et 2 MB en sortie, limite qui porte sur la représentation JSON sérialisée des données. Un PDF de rapport, un jeu d’images ou un export CSV volumineux la franchissent sans effort, et le workflow échoue avec une erreur de sérialisation.

La solution tient en une phrase : faites transiter des références, jamais des charges utiles. L’activité télécharge la donnée depuis un stockage externe, la traite localement où elle n’est bornée que par la mémoire du worker, puis renvoie l’URL du résultat.

@workflows.activity()
async def traiter_gros_fichier(fichier_url: str) -> dict:
    """Télécharge, traite et re-upload le fichier.
    Seules les URLs transitent par le workflow."""
    async with httpx.AsyncClient() as client:
        # Télécharger depuis S3/GCS
        response = await client.get(fichier_url)
        contenu = response.content  # Peut faire 100 MB

        # Traiter le fichier
        resultat = traiter(contenu)

        # Uploader le résultat
        await client.put(
            "https://storage.example.com/résultats/output.json",
            content=resultat
        )

    return {"url_resultat": "https://storage.example.com/résultats/output.json"}

Le budget d’événements et de volume

Chaque exécution est plafonnée à 51 200 événements. La plateforme en génère un à chaque démarrage d’activité, chaque complétion d’activité, chaque signal reçu et chaque timer déclenché. En pratique, un appel d’activité coûte environ deux à trois événements une fois les métadonnées comptées, ce qui met un workflow de cent activités aux alentours de 250 à 300 événements. Autrement dit, le plafond autorise quinze à vingt mille appels d’activité par exécution : largement au-delà de ce que réclame la plupart des cas d’usage.

Vous ne rencontrerez donc cette limite que sur des traitements de masse — parcourir cinquante mille documents dans une seule exécution, par exemple. Le pattern de continuation, détaillé dans la leçon suivante, résout ce cas : le workflow traite un lot, puis lance un nouveau workflow pour le lot suivant, remettant le compteur d’événements à zéro.

La seconde borne porte sur le volume : la taille cumulée de tous les événements d’une exécution ne doit pas dépasser 50 MB. Elle se remplit d’autant plus vite que vos activités renvoient des objets riches, puisque chaque résultat est écrit dans le journal. Le même réflexe s’applique — retourner un identifiant plutôt qu’une structure complète, stocker les résultats intermédiaires dans un service externe, paginer les traitements en lots — et il suffit dans l’immense majorité des cas.

Aucune I/O dans le workflow

La dernière ligne du tableau n’est pas une limite de dimensionnement mais une règle de conception, déjà rencontrée avec le déterminisme. Le code du workflow ne doit contenir aucune opération d’entrée/sortie : ni appel réseau (httpx, aiohttp, requests), ni lecture ou écriture de fichier (open, aiofiles), ni accès base de données, ni lecture de variables d’environnement destinée à orienter un branchement. Toutes ces opérations vivent dans les activités, dont les résultats sont journalisés et donc rejouables à l’identique.

Points clés à retenir

  • 2 secondes de latence minimum entre chaque activité — regroupez les opérations liées
  • 2 MB maximum par input/output d’activité — utilisez un stockage externe pour les données volumineuses
  • 51 200 événements et 50 MB maximum par exécution — utilisez le pattern de continuation pour les très longs workflows
  • Aucune I/O dans le code du workflow — tout va dans les activités
  • Ces limitations sont liées à l’architecture Temporal sous-jacente et à la Public Preview