PlantUML Activity Diagram Syntax & Examples
Reference for PlantUML activity diagram syntax — start / stop, actions, if-else branches, repeat-while loops, switch-case, and swimlane lanes. Copy-paste examples.
Syntax reference, layout guidance, and ready-to-open examples for this diagram type.
A syntax reference for the PlantUML activity-beta grammar — read this when you need to know exactly how a particular construct (decision, loop, lane, fork) is written, then beautify or edit the source in the editor.
PlantUML activity-beta constructs, one per row
| Construct | Syntax | Notes |
|---|---|---|
| Diagram terminals | start … stop | Both are required. Omit them and the parser falls back to the legacy (*) syntax. |
| Action node | :Action; | Text sits between the colon and the semicolon. A missing ; silently swallows the next line — the most common syntax bug on this grammar. |
| Two-way decision | if (Condition?) then (yes) … else (no) … endif | The branch labels in parentheses are what appear on the outgoing edges. |
| Chained decision | elseif (Condition?) then (yes) | Chains onto an open if before its else. Repeat as many times as needed. |
| Multi-way decision | switch (Test?) case (A) … case (B) … endswitch | Use when the branches are named alternatives rather than yes/no. |
| Test-last loop | repeat … repeat while (Condition?) is (yes) | Body runs before the test — the do-while shape. Typical for retry patterns. |
| Test-first loop | while (Condition?) … endwhile | Test runs before the body. Typical for queue processing. |
| Loop exit label | ->no; | Optional annotation on the exit edge, to say what the false condition means in context. |
| Swimlane lane | |Customer| | Declares a lane, or switches to one already declared. Actions belong to the most recent lane. |
| Coloured lane | |#FFB6C1|Monitoring| | Named CSS colour or hex. The colour only needs to appear on the first declaration. |
| Parallel paths | fork … fork again … end fork | Renders with the default layout rather than the beautified one. |
| Branch terminator | stop | Inside a branch this ends that path only, not the whole diagram. |
Syntax reviewed
View PlantUML sourcePlain-text diagram syntax — copy or edit directly.
1@startuml2|Employee|3start4:Submit reimbursement;5|Manager|6:Review request;7if (Approved?) then (yes)8 |Finance|9 :Process payment;10 :Notify employee;11else (no)12 |Employee|13 :Receive rejection;14endif15stop16@endumlWhat is a PlantUML activity diagram
An activity diagram in PlantUML describes a process as an ordered sequence of actions, with branches, loops, and parallel paths along the way. It is the closest PlantUML equivalent to a flowchart — but with a strict grammar (start / :action; / stop) and built-in support for swimlane lanes, which makes it the standard choice for runbooks, approval flows, and process documentation. PlantUML actually ships two activity syntaxes: the legacy one (using (*) and arrow notation) and the modern activity-beta (start / action / stop). Everything on this page covers activity-beta, which is what @startuml / @enduml blocks render by default in current PlantUML releases.
Basic syntax — start, action, stop
Every activity diagram lives inside a @startuml / @enduml block. The flow begins at start, runs through a series of actions written as :Action text; (note the trailing semicolon), and ends at stop (or end for early termination). Actions can be plain strings, multi-line with \n, or include inline formatting. Each action becomes one rounded rectangle in the rendered output, and the renderer connects them top-to-bottom by default. This is the minimum viable activity diagram and the building block every other construct extends.
startandstopare required terminals — omit them and the parser falls back to legacy syntax:Action;is the basic activity node — text inside the colons, semicolon at the end- Multi-line action labels use
\ninside the colons
Branching — if-else and switch-case
Decisions in PlantUML activity use if (Condition?) then (yes) ... else (no) ... endif. The condition is rendered as a diamond, and the (yes) / (no) labels appear on the outgoing edges. For multi-way decisions, use switch (Variable?) ... case (A) ... case (B) ... endswitch — each case becomes a separate path that converges at the end of the switch. Both forms can be nested and combined with loops; the parser handles arbitrarily deep nesting, but practical readability degrades past two levels.
if (Condition?) then (yes) ... else (no) ... endif— basic two-way decisionif (...) then (yes) ... elseif (...) then (yes) ... else (no) ... endif— chained decisionsswitch (...) case (A) ... case (B) ... endswitch— multi-way decision with named branches
Looping — repeat-while and while-do
PlantUML activity offers two loop constructs that differ in when the condition is evaluated. repeat ... repeat while (Condition?) is (yes) runs the body first, then tests — equivalent to a do-while loop. while (Condition?) ... endwhile tests first, then runs the body — equivalent to a standard while loop. The first form is typical for retry patterns (attempt the action, then check whether to retry); the second is typical for queue processing (check whether there's work, then process it). Both forms accept an optional ->no; or ->yes; annotation on the exit edge to label what the false condition means in context.
Swimlane lanes — partition responsibility across actors
Swimlane lanes are PlantUML activity's standout feature. Declare a lane with |Lane Name| before the first action that belongs in it; subsequent actions belong to the most recently declared lane until another |Other Lane| switches context. Optionally tint the lane with |#Color|Lane Name| — colors can be named CSS values or hex. The reference renderer stacks lanes vertically as subgraphs, but Beauty Diagram's renderer lays them out as horizontal columns by default once at least two lanes and one cross-lane edge are present. That column layout is what makes the diagram read as a process across actors rather than a vertical sequence with labels.
|Customer|— plain lane declaration|#FFB6C1|Monitoring|— coloured lane declaration with hex tint|Lane Name|re-used later switches the active lane without redefining it
Common patterns & gotchas
A few patterns come up repeatedly. Approval flows usually combine swimlanes with if-else — the approver lane has the decision, the receiver lane handles each outcome. Retry flows pair repeat-while with a status check. Forks and joins for parallel paths use fork ... fork again ... end fork — supported but rendered with default layout, not yet beautified. The most common gotcha: forgetting the semicolon on :Action; causes the parser to swallow the entire next line silently — if your diagram is missing a node, check the previous line for a missing ; first.
- Missing
;on:Action;silently swallows the next line — most common syntax bug - Lanes only switch to horizontal columns when ≥ 2 lanes + ≥ 1 cross-lane edge exist
stopinside a branch terminates only that branch path, not the whole diagram