All posts
MermaidFlowchartsLoopsIterationProcess Design

Mermaid flowchart loop syntax: repeat and iteration patterns

7 min readThe MermaidCreator team

Loops are everywhere in real workflows: "retry until success," "process each item in a batch," "repeat until the condition changes." Most flowchart tools force you to draw the same box multiple times with arrows looping back—cluttered and hard to read. Mermaid's loop node solves this with a single, reusable abstraction that makes iteration intent crystal clear.

This guide teaches you Mermaid loop syntax, shows practical patterns from API retry logic to data pipelines, and explains when to use loops versus other control structures.

What a loop node represents

A loop node (shown as a rectangle with a curved left edge, sometimes called a "repeat" or "do-while" symbol) represents one or more repetitions of an action or group of actions.

flowchart TD
    A([Start]) --> B["Initialize counter"]
    B --> C{counter < 10?}
    C -->|Yes| D["Process item"]
    D --> E["Increment counter"]
    E --> C
    C -->|No| F([End])

This is the traditional way—explicit arrows, explicit decisions. It's clear but verbose. The same logic as a loop node:

flowchart TD
    A([Start]) --> B["Initialize counter"]
    B --> C{{"Process while counter < 10"}}
    C --> D["Increment counter"]
    D --> C
    C --> E([End])

Wait—Mermaid doesn't have a native "loop node" shape like Visio does. So we use subgraphs with a label to represent loops semantically, or we use alt blocks in sequence diagrams for loops. Let me clarify with the actual Mermaid pattern.

Mermaid loop patterns

Pattern 1: Explicit loop with a decision diamond

The most readable pattern uses a decision diamond + arrow feedback:

flowchart TD
    A([Start]) --> B["Initialize: items = []"]
    B --> C["Fetch page 1"]
    C --> D["Add items to list"]
    D --> E{More pages?}
    E -->|Yes| F["page += 1"]
    F --> C
    E -->|No| G["Return items"]
    G --> H([End])

How to read it:

  • Start with initialization
  • Do the action (fetch, process, etc.)
  • Check the loop condition
  • If true, loop back (the arrow from E back to C)
  • If false, exit

Pattern 2: Retry loop for error handling

A common pattern: try something, catch errors, retry with exponential backoff:

flowchart TD
    A([Start payment]) --> B["Attempt charge"]
    B --> C{Payment approved?}
    C -->|Yes| D["Confirm order"]
    D --> E([Success])
    C -->|No| F{Retries < 3?}
    F -->|Yes| G["Wait 2^n seconds"]
    G --> H["Increment retry count"]
    H --> B
    F -->|No| I["Email customer"]
    I --> J([Failed])

Key insight: The inner loop (B → C → F → G → H → B) repeats the charge attempt. When retries are exhausted, it breaks to J (failed path).

Pattern 3: Data processing loop (map over collection)

Process every item in a collection:

flowchart TD
    A([Start]) --> B["items = get_all_users()"]
    B --> C["index = 0"]
    C --> D{index < items.length?}
    D -->|Yes| E["user = items[index]"]
    E --> F["Send reminder email"]
    F --> G["index += 1"]
    G --> D
    D -->|No| H["Log: completed"]
    H --> I([End])

Real-world: Daily email campaign that loops through all users, sends reminders, then marks done.

Pattern 4: Nested loops (loops within loops)

Process a matrix (e.g., rows and columns):

flowchart TD
    A([Start]) --> B["row = 0"]
    B --> C{row < 10?}
    C -->|Yes| D["col = 0"]
    D --> E{col < 10?}
    E -->|Yes| F["matrix[row, col] *= 2"]
    F --> G["col += 1"]
    G --> E
    E -->|No| H["row += 1"]
    H --> C
    C -->|No| I([End])

Structure:

  • Outer loop: rows (C → ... → H → C)
  • Inner loop: columns (E → ... → G → E)
  • Each cell (F) runs once per inner iteration

Use clear naming (row, col) to distinguish loop variables.

Real-world examples

CI/CD pipeline with retry logic

flowchart TD
    A([PR merged]) --> B["Run tests"]
    B --> C{Tests pass?}
    C -->|Yes| D["Build artifact"]
    D --> E["Deploy to staging"]
    E --> F{Smoke tests pass?}
    F -->|Yes| G["Deploy to production"]
    F -->|No| H["Rollback"]
    H --> I["Alert team"]
    I --> J([Failed])
    C -->|No| K{Retries < 2?}
    K -->|Yes| L["Clear cache"]
    L --> B
    K -->|No| M["Notify developers"]
    M --> J
    G --> N([Success])

Loops here:

  • Test retry (B → C → K → L → B): re-run tests if they fail (up to 2 times)
  • Smoke test feedback (F → H → I → J): on failure, rollback and alert

Data pipeline with batching

flowchart TD
    A([Start]) --> B["batch = []"]
    B --> C["Read next record"]
    C --> D["Add to batch"]
    D --> E{batch.size == 1000?}
    E -->|Yes| F["Send batch to warehouse"]
    F --> G["Reset batch"]
    G --> B
    E -->|No| H{More records?}
    H -->|Yes| B
    H -->|No| I{batch is not empty?}
    I -->|Yes| F
    I -->|No| J([Complete])

Loop insight: Processes records one by one, accumulates a batch, sends when full (1000 items), then resets and continues. At the end, sends any remaining partial batch.

Cleanup loop (repeat until a resource is freed)

flowchart TD
    A([Request: delete old files]) --> B["today = now()"]
    B --> C["file = oldest file"]
    C --> D{file exists?}
    D -->|Yes| E{file age > 30 days?}
    E -->|Yes| F["Delete file"]
    F --> G["freed += file.size"]
    G --> H["Next file"]
    H --> D
    E -->|No| I["Stop"]
    D -->|No| I
    I --> J["Return freed"]
    J --> K([End])

Loop: Iterate over files, delete old ones, free up disk space. Stops when no more old files exist.

Loop vs. alt blocks in sequence diagrams

Flowchart loops show iteration logic. Sequence diagrams show interactions over iterations using loop blocks:

sequenceDiagram
    participant Client
    participant API

    Note over Client: Retry loop: up to 3 attempts
    loop Retry until success or 3 attempts
        Client->>API: POST /data
        alt Success
            API-->>Client: 200 OK
            break
        else Timeout
            API-->>Client: 504 Timeout
        end
    end

When to use each:

  • Flowchart loop → show the decision tree and retry logic (business process)
  • Sequence diagram loop → show which systems are involved in each iteration (technical implementation)

Ideally, use both in your documentation.

Best practices for readable loops

1. Label loop conditions clearly

Bad:

C -->|Yes| B

Good:

C -->|More items to process| B

2. Show loop initialization

Always initialize before the loop. Readers need to see where counter, batch, or index starts:

flowchart TD
    A([Start]) --> B["counter = 0"]
    B --> C{counter < 10?}
    C -->|Yes| D["Do work"]
    D --> E["counter += 1"]
    E --> C

Without B, it's unclear what counter is or where it comes from.

3. Make the exit condition obvious

The "No" or "False" path from the loop condition should lead out of the loop. Don't hide it:

flowchart TD
    A --> B{Continue?}
    B -->|Yes| C["Action"]
    C --> D["Update state"]
    D --> B
    B -->|No| E["Exit"]
    E --> F([End])

4. Use consistent variable names

If you have multiple loops, use consistent names:

  • index / counter for numeric iteration
  • item for collection items
  • retries for retry counts
  • batch for accumulated data

Comparison with similar patterns

PatternBest forExample
LoopRepeating a process until a conditionRetry logic, batching, polling
If-then-elseOne-time decisionRoute based on status
SubgraphGrouping related stepsA phase or sub-process
Parallel (swimlanes)Concurrent tasksMultiple teams/systems

Most workflows combine these: an outer loop with if-then-else branches inside it.

FAQ

Can I loop based on external input (e.g., "ask the user to try again")?
Yes. The decision diamond can represent a human choice or a system state check. Both cause loops:

flowchart TD
    A["Attempt operation"]
    B{Success?}
    B -->|No| C["Show error to user"]
    C --> D{Try again?}
    D -->|Yes| A
    D -->|No| E([Cancel])

What's the difference between a loop and recursion?
Loops iterate in a sequence; recursion is a function calling itself. Mermaid flowcharts show loops visually. For recursion (e.g., a tree traversal function), flowcharts can represent it, but sequence diagrams often make it clearer:

sequenceDiagram
    participant Main
    participant Func

    Main->>Func: traverse(node)
    alt node is leaf
        Func-->>Main: return
    else node has children
        Func->>Func: traverse(left child)
        Func->>Func: traverse(right child)
        Func-->>Main: return
    end

How do I show a "do-while" loop (run first, check after)?
In flowcharts, do-while is just a loop where the check comes after the action:

flowchart TD
    A([Start]) --> B["Attempt"]
    B --> C{Succeeded?}
    C -->|No| B
    C -->|Yes| D([End])

The action (B) always runs at least once before the check (C).

Can I nest loops more than 2 levels deep?
Technically yes, but it gets hard to read. Beyond 2–3 levels, consider extracting the inner loop into a separate diagram or a sub-process box.

Master loop patterns in the MermaidCreator editor—build a retry workflow, a batch processor, or a cleanup script to see how loops make iteration logic shine.

Related posts