Mermaid loop and alt blocks: conditional flows explained
Most real workflows branch. A payment API retries on timeout. Auth returns 401 on invalid credentials. A polling worker loops until the job completes. Sequence diagrams that ignore these branching paths teach a false simplicity.
Mermaid's alt, else, and loop blocks let you show decision logic and retries inside a single diagram without repeating arrows or splitting across multiple drawings.
alt/else blocks for branching
The alt block (alternation) works like an if/else statement in code. You write one flow path, mark the condition, then show what happens if the condition is false:
sequenceDiagram
participant C as Client
participant API as Payment API
participant DB as Database
C->>API: POST /charge { amount, card }
API->>DB: SELECT card_token WHERE card_id=?
DB-->>API: token (or null)
alt Card found
API->>API: Process charge with token
API-->>C: 200 OK { transaction_id }
else Card not found
API-->>C: 400 Bad Request { error }
end
The alt block reads naturally: if the condition in the label is true, follow the top path; otherwise, follow the else path. Readers don't need two separate diagrams — both outcomes live in one.
Multiple branches with else if
For more than two branches, chain else if (written as else in Mermaid):
sequenceDiagram
participant C as Client
participant Auth as Auth Service
participant DB as User DB
C->>Auth: POST /login { email, password }
Auth->>DB: SELECT * FROM users WHERE email=?
DB-->>Auth: User record (or null)
alt User found
Auth->>Auth: Verify password hash
alt Password matches
Auth-->>C: 200 OK { token }
else Password invalid
Auth-->>C: 401 Unauthorized
end
else User not found
Auth-->>C: 404 Not Found
end
Stack alt/else blocks to model cascading decision trees. Each condition gets its own line of reasoning.
loop blocks for retries and polling
The loop block shows repeated actions without forcing you to copy arrows multiple times. It's perfect for retries, polling, and any "keep doing this until condition X" pattern:
sequenceDiagram
participant C as Client
participant API as Job API
participant Worker as Background Worker
C->>API: POST /jobs { task: "process-data" }
API-->>C: 202 Accepted { job_id: 42 }
loop Poll every 2 seconds (max 10 attempts)
C->>API: GET /jobs/42/status
API-->>C: { status: "processing" }
end
C->>API: GET /jobs/42/status
API-->>C: { status: "done", result: "..." }
The label describes the loop condition — readers see immediately that the client polls repeatedly until the job finishes.
Combining loop and alt for robust flows
Real systems combine both. Here's a fetch-with-retries pattern:
sequenceDiagram
participant C as Client
participant API as Downstream API
C->>API: GET /resource/123
loop Retry up to 3 times on timeout
alt Responds within 5s
API-->>C: 200 OK { data }
break
else Timeout
Note right of C: Retry...
end
end
The break statement exits the loop when the condition succeeds. Readers see the retry strategy without a wall of arrows.
Practical patterns
Exponential backoff retry (conceptual):
sequenceDiagram
participant C as Client
participant API as External API
C->>API: POST /webhook-notify
loop Retry with backoff (1s, 2s, 4s, 8s)
alt Responds with 2xx
API-->>C: Success
break
else 5xx server error
Note right of C: Wait, then retry
else Network timeout
Note right of C: Wait, then retry
end
end
Cascading fallbacks:
sequenceDiagram
participant C as Client
participant Cache as Redis Cache
participant DB as Primary DB
participant Backup as Backup DB
C->>Cache: GET user:42
alt Cache hit
Cache-->>C: { user }
else Cache miss
C->>DB: SELECT * FROM users WHERE id=42
alt Primary responds
DB-->>C: { user }
else Primary timeout
C->>Backup: SELECT * FROM users WHERE id=42
Backup-->>C: { user }
end
end
When to use each block
alt/else: Your flow has a decision point. Show both branches inline rather than as separate diagrams. One diagram, two paths.
loop: The same action repeats. Polling, retries, batch processing. The loop label tells readers the termination condition.
Combine both: Error-recovery patterns where you loop on a condition and break on success.
Avoiding over-complexity
A rule of thumb: if your diagram has more than 3 nested blocks or loops, consider splitting it into two diagrams. A readable diagram teaches; a crowded one confuses.
Split when:
- The loop or alt block is conceptually separate (e.g., "here's the happy path; here's error recovery")
- The diagram is longer than a typical function (roughly 15–20 lines of Mermaid syntax)
- A second diagram would make the first easier to explain
Keep it focused. A diagram about JWT auth doesn't need to show the full retry strategy for the database query; mention it in prose instead.
FAQ
Q: Can I use && or || logic in alt conditions? A: The condition text is just a label for readers — it's not executable. Write what makes sense in plain English: "Retry count < 3 and timeout", "User has admin role or owns resource", etc.
Q: What's the difference between loop and par?
A: loop shows sequential repetition (do this multiple times in a row). par (parallel) shows concurrent actions. Use loop for retries and polling.
Q: How do I show an else if without nesting?
A: Write multiple else blocks inside one alt. Each else label describes a new condition branch.
Try drawing your next error-recovery pattern in the MermaidCreator editor — seeing loops and alts render makes the syntax stick fast.
Related posts
Flowchart vs sequence diagram: when to use each in Mermaid
Both show process flows, but flowcharts model decisions and branches while sequence diagrams trace interactions over time. Here's how to pick the right one.
How to document REST APIs with Mermaid sequence diagrams
Sequence diagrams turn scattered endpoint descriptions into readable request-response flows — and Mermaid keeps them version-controlled right beside your code.