Skip to content
MermaidViewer

Diagrams

A sequence diagram with loop, alt, and parallel

A sequence diagram with loop is how you show a retry or a poll without pasting the same two arrows five times. loop wraps the messages. end closes that wrap.

By MermaidViewer editorsUpdated 10 min read

A sequence diagram with loop is how you show a retry or a poll without pasting the same two arrows five times. loop wraps the messages that repeat, and end closes that wrap. The same closer discipline applies to alt, opt, and par. Each block you open needs its own end. Forget one and the preview dies on the next line, which feels like a mysterious syntax error and is usually just an unclosed retry.

I reach for a loop when the story says "try again" or "keep asking until." I reach for alt when two replies are mutually exclusive. Those are different ideas, and they stack: a decline can contain a retry. The arrow shapes and the participant rules live in the sequence diagram tutorial, and the keyword list sits on the sequence diagram syntax page. This page is the blocks, the closers, and two charts that use them on purpose.

Each opener gets a closer

Mermaid treats these as regions, not as indentation. The indent is for you. The parser counts keywords.

  • alt opens a fork. else is another side of that same fork. end closes it.
  • loop opens a repeat. The text after loop is the title, such as how many tries or what you are waiting for. end closes it.
  • opt opens a single optional region. There is no else. end closes it.
  • par opens parallel work. and separates a parallel arm. end closes the whole parallel region.

Nesting is allowed. A loop inside an else is a normal retry. The inner end closes the loop. The outer end closes the alt. If you write one end and hope it closes both, the outer block stays open and every message after it falls inside the branch you thought you had left. I debug this by counting. Openers on one line of a scratch note, closers on the next. They match before I believe the picture.

else only means something inside an alt. An else after a loop is a parse error, not a poetic way to say "otherwise stop." If you need "retry, and if that still fails, give up," the give-up is either inside the loop's last iteration, which is hard to draw honestly, or it is the message after the loop's end. I put it after. The loop title says "while attempts remain." The message after the loop is the outcome.

Do not name a participant end. That word is the closer. Call the actor User or Worker and move on.

A retry lives inside the decline

Card charges are the example I trust because everyone has watched one fail. The worker asks payments, payments asks the bank, and the bank either approves or declines. On the decline, the worker retries while attempts remain. A receipt goes out only if someone asked for one. That last part is an opt, because the story does not always include it.

mermaid
sequenceDiagram
  participant Worker
  participant Pay as Payments
  participant Bank
  Worker->>Pay: Charge the card
  Pay->>Bank: Authorize
  alt Approved
    Bank-->>Pay: OK
    Pay-->>Worker: Paid
  else Declined
    Bank-->>Pay: No
    loop Retry while attempts remain
      Worker->>Pay: Charge again
      Pay->>Bank: Authorize
      Bank-->>Pay: Result
    end
    Pay-->>Worker: Final status
  end
  opt Receipt was requested
    Worker->>Pay: Send the receipt
    Pay-->>Worker: Receipt queued
  end
Open in the live editor

Read the closers from the inside. The loop's end sits before Pay-->>Worker: Final status, so the final status is still inside the declined branch and outside the retry. The alt's end sits before the opt, so the receipt is not a third outcome of the bank. It happens after you know the charge conversation is over. I had an earlier draft with the opt inside the approved branch only. That matched a different policy, "receipts only on success," which this story did not say. The position of the block is the policy. A caption that disagrees with the position will lose.

The loop body is three arrows, not a novel. Put the backoff, the idempotency key, and the maximum count in the paragraph under the figure. The title "Retry while attempts remain" is the contract the arrows can hold. If the maximum is three, you may write loop Up to 3 charges and keep the number in one place. Writing "attempt 2 of 3" inside the message duplicates the title and goes stale when the constant changes.

Solid arrows are requests. Dotted arrows are replies. Inside a loop this matters more, because a reader scanning quickly will treat every solid arrow as another charge against the customer. The bank's Result is a reply. Draw it as one.

A poll is a loop with a dull body

Polling looks different from a retry. A retry says the previous answer was no. A poll says you do not have a terminal answer yet, so you ask again. The body of a poll should look boring. If it contains a whole business process, you have stuffed the process into the wait.

Checkout places an order, then the page asks for status until the payment settles. After the loop, alt splits paid from failed. Those are the terminal replies. They do not belong inside the loop, or the picture claims you might be paid and unpaid on every tick.

mermaid
sequenceDiagram
  actor UI as Checkout
  participant API as Orders
  participant Pay as Payments
  participant Mail as Mailer
  UI->>API: Place the order
  API->>Pay: Start the charge
  Pay-->>API: Accepted
  loop Poll until settled
    UI->>API: Ask for status
    API-->>UI: Still pending
  end
  alt Paid
    API-->>UI: Show the receipt
  else Failed
    API-->>UI: Show the failure
  end
  par Record and notify
    API->>Pay: Store the outcome
  and
    API->>Mail: Queue the mail
  end
Open in the live editor

The par is the part people fake with two arrows in a row and the word "meanwhile" in a label. par says the record and the mail are not ordered by this diagram. and splits the arms. One end closes both. If the mail must happen only after the outcome is stored, delete the par and draw two normal arrows. Parallel syntax is a claim that order does not matter. I use it rarely, because most "meanwhile" comments in tickets are actually ordered and someone will get paged when the mail races the write.

and with no title is legal. I still prefer a word on the par line, "Record and notify," so a reviewer knows why the split exists. An untitled parallel block is how a diagram grows a third arm during a refactor and nobody remembers the original reason.

The loop shows one pending reply, not five copies. That is the point of the construct. If you need to show that the second poll returns paid, you do not want a loop. You want the messages written out, because the iterations differ. A loop promises the body is the repeating shape. When the shape changes, unroll it or move the interesting reply to after the end, which is what the alt is doing here.

Titles are doing more work than the arrows

The text after loop, alt, opt, and par is the only place a condition fits without turning an arrow into a paragraph. I write the condition the way the code reads. "Retry while attempts remain" matches a counter. "Poll until settled" matches a status that is not terminal. "Receipt was requested" matches a flag. Cute titles age badly. "The scary part" means nothing in a review six weeks later.

alt labels its sides with the line after alt and the line after else. "Approved" and "Declined" are enough. Restating them in the arrow text, "OK which means approved," doubles the noise. The sequence alt patterns go further on forks, including the case with more than one else. Use that when the branch is the whole article you need. Use a loop page, this one, when the repeat is the part your current diagram is missing.

opt has one title and no alternative arm. If you hear yourself wanting an else, you wanted alt. I convert it rather than drawing the missing arm as a note. Notes drift. Arms render.

Empty blocks parse and say nothing. A loop with no messages inside is a mistake I have committed while rearranging lines. Delete it. A region with no arrows looks like a rendering bug to the next reader, and they will "fix" your policy while trying to fix the picture.

What the loop does not mean

A loop is not a timer diagram. It does not draw the clock, the jitter, or the give-up deadline. Those are sentences. I write them under the fence: "Two seconds between polls, stop after thirty seconds, then take the failed branch." The chart shows that the ask repeats and that paid and failed are outside the repeat. Someone who implements a busy loop from the picture alone ignored the paragraph. That is still partly my fault if the paragraph was three screens below. Keep the sentence adjacent.

A loop is also not permission to hide a branch. I have wrapped an alt inside a loop so tightly that every iteration looked like it might refund the customer. If only the last iteration can refund, the refund arrow sits after the loop. Repeating a side effect inside the body says the side effect repeats. Money arrows inside a loop title should make you suspicious of yourself. Read them aloud with the word "again."

The worked sequence examples are worth a look when you want to see a full cast without another lesson attached. The password-reset story shows how to get from a sentence to a first diagram. Add a loop only after that first diagram is true. A retry on a chart that has the wrong actors is a precise picture of the wrong system.

Participants stay declared before the first message, in the left-to-right order the story uses. In the poll chart the checkout UI is on the left because the human is there, and the mailer is on the right because it is a side effect. If the mailer appears first, Mermaid will place it first, and the eye will think the story starts at the mailbox. Declare the lanes. Then open the blocks.

Mistakes that look like style

Missing colon. Worker->>Pay Charge again is not a message. The parser wants Worker->>Pay: Charge again. I drop the colon while editing in a hurry, the preview points at the line, and I blame the loop because that is the keyword I just learned. Check the colon before you rewrite the block.

par closed with a second end for each arm. Arms are separated by and. Only the region closes. An extra end will close the alt you opened earlier, and the rest of the chart silently changes meaning if it parses at all. Count again.

A loop title with parentheses left unquoted can get fussy on some builds, depending on the characters. I keep titles as plain words. "Up to 3 charges" survives. If you truly need punctuation, keep it in the paragraph. The OAuth sequence template is a longer handshake you can compare against: several legs, a clear order, and room to add a refresh as a later opt without stuffing it into the first arrow.

Autonumbering is optional. I turn it on when a review comment needs to say "step 4." I leave it off when the loop makes the numbers feel like iteration counts. They are not. They are message indexes. Mixing "step 4" with "attempt 2" in one review thread is how two people debug different things.

The free sequence diagram maker path is fine for a draft. Paste, then add the closers yourself if the draft used copy-paste arrows instead of a loop. Generated charts love to unroll a poll into three identical pairs. Replace the copies with one loop. The picture gets shorter and the policy gets clearer, which is the rare edit that does both.

Put the closer where the policy changes

When I review these diagrams I look at end lines before I look at labels. Each end is a claim that a region stopped and the next message is outside it. If the final status is inside the retry, the product will send "final" on every attempt. If the receipt opt is inside the declined branch only, successful charges never get a receipt. The keywords are the design.

Open the editor and paste the charge chart. Break one end on purpose, watch the preview fail, then put it back. That thirty seconds teaches the closer rule better than another paragraph. The editor is free without an account, and the preview is live. The AI sequence generator can draft a loop from a sentence like "retry the charge up to three times, then report status," and it can fix a missing closer. Free accounts include 5 AI uses in total. Spend one on a fix if you are tired. Still read the end lines yourself. The generator does not know whether the receipt is optional in your business. You do.

Frequently asked questions

Does loop mean the messages run forever?

It means they repeat. Put the stop condition in the loop title, such as 'until empty' or '3 attempts'. The diagram will not enforce it.

Can I nest alt inside loop?

Yes. Each block needs its own end. An else without an alt is a parse error.

What is par for?

Messages that happen side by side rather than in order. If the order matters, it is not par.