Skip to main content
Lesson 10 of 14 · Mistral Workflows: Durable Orchestration

Platform Limitations

Lesson 10 of 14 Updated July 29, 2026 Advanced
On this page
  1. Know the Limits
  2. Two Seconds Between Each Activity
  3. Two Megabytes Per Invocation
  4. The Event and Volume Budget
  5. No I/O in the Workflow
  6. Key Takeaways

Know the Limits

The Mistral Workflows platform is in Public Preview (as of April 2026). Like any orchestration system, it imposes technical constraints that you must understand to design robust workflows. These limits aren’t just documentation footnotes; they show up in production, often late in the game, as serialization errors or workflows terminated unexpectedly with no warning in your code. Knowing them upfront changes how you structure your processing logic.

The table below summarizes the key constraints and the concrete consequence of exceeding each one.

Limitation Value Consequence if exceeded
Delay between activities 2 seconds Unavoidable latency between each activity call
Input/output per invocation 2 MB Serialization error, workflow fails
Events per execution 51,200 Workflow forcibly terminated
Total size per execution 50 MB Workflow forcibly terminated
Default timeout 1 hour Workflow cancelled (configurable up to 7 days)
Maximum timeout 7 days Workflow automatically cancelled
I/O in workflows Forbidden Non-determinism error during replay

Two Seconds Between Each Activity

The platform enforces a minimum 2-second delay between activity calls. This latency isn’t a teething problem; it’s inherent to the orchestration architecture, which persists every event before proceeding. It’s the price of durability.

The impact is easy to calculate and often surprising. A workflow chaining ten sequential activities consumes at least twenty seconds of orchestration time, regardless of how long the activities themselves take. If each activity runs in fifty milliseconds, you’ve designed a half-second job that takes twenty seconds to return a result.

The workaround is to bundle operations that don’t need to be separate into a single activity. Compare these two versions of the same NLP pipeline.

# SUBOPTIMAL: 3 activities = 6 seconds of orchestration latency
@workflows.workflow.define(name="pipeline_lent")
class SlowPipeline:
    @workflows.workflow.entrypoint
    async def run(self, text: str) -> dict:
        tokens = await tokenize(text)
        embeddings = await calculate_embeddings(tokens)
        clusters = await cluster(embeddings)
        return clusters

# OPTIMIZED: 1 activity = 2 seconds of orchestration latency
@workflows.activity()
async def complete_nlp_processing(text: str) -> dict:
    tokens = tokenize_local(text)
    embeddings = calculate_embeddings_local(tokens)
    clusters = cluster_local(embeddings)
    return {"clusters": clusters}

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

The rule for splitting becomes simple: create a separate activity only if you need the persistence guarantee between two operations. If two operations can fail together without causing issues—like local tokenization and embedding calculation chained in memory—bundle them.

Two Megabytes Per Invocation

Each activity call is limited to 2 MB for input and 2 MB for output, based on the serialized JSON representation of the data. A report PDF, a set of images, or a large CSV export will easily exceed this, causing the workflow to fail with a serialization error.

The solution is one sentence: pass references, never payloads. The activity downloads the data from external storage, processes it locally (where it’s limited only by the worker’s memory), and returns the result URL.

@workflows.activity()
async def traiter_gros_fichier(fichier_url: str) -> dict:
    """Download, process, and re-upload the file.
    Only URLs pass through the workflow."""
    async with httpx.AsyncClient() as client:
        # Download from S3/GCS
        response = await client.get(fichier_url)
        contenu = response.content  # Could be 100 MB

        # Process the file
        resultat = traiter(contenu)

        # Upload the result
        await client.put(
            "https://storage.example.com/résultats/output.json",
            content=resultat
        )

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

The Event and Volume Budget

Each execution is capped at 51,200 events. The platform generates an event for every activity start, every activity completion, every signal received, and every timer triggered. In practice, an activity call costs about two to three events once metadata is counted, putting a hundred-activity workflow around 250 to 300 events. In other words, the cap allows fifteen to twenty thousand activity calls per execution: far beyond what most use cases require.

You’ll only hit this limit with bulk processing—for example, iterating through fifty thousand documents in a single execution. The continuation pattern, detailed in the next lesson, solves this: the workflow processes a batch, then launches a new workflow for the next batch, resetting the event counter.

The second bound concerns volume: the cumulative size of all events in an execution must not exceed 50 MB. This fills up faster if your activities return rich objects, since every result is written to the log. The same reflex applies—return an identifier rather than a full structure, store intermediate results in an external service, paginate processing in batches—and it suffices in the vast majority of cases.

No I/O in the Workflow

The last line of the table isn’t a sizing limit but a design rule, already covered under determinism. Workflow code must contain no input/output operations: no network calls (httpx, aiohttp, requests), no file reading or writing (open, aiofiles), no database access, and no reading of environment variables to steer branching. All these operations live in activities, whose results are logged and therefore replayable identically.

Key Takeaways

  • 2 seconds minimum latency between each activity—bundle related operations
  • 2 MB maximum per activity input/output—use external storage for large data
  • 51,200 events and 50 MB maximum per execution—use the continuation pattern for very long workflows
  • No I/O in workflow code—everything goes in activities
  • These limitations stem from the underlying Temporal architecture and the Public Preview status