When you model real software behavior, not everything follows a straight line. Users log in or they don't. Payments succeed or they fail. A server responds or times out. If your sequence diagrams only show the happy path, they're incomplete. PlantUML sequence diagram code examples with conditional logic let you capture branching behavior the "if this, then that" decisions so your diagrams actually reflect how a system works. This is especially useful for documenting APIs, user flows, error handling, and microservice interactions where outcomes vary based on runtime conditions.

What does conditional logic mean in a PlantUML sequence diagram?

Conditional logic in a sequence diagram refers to blocks that show different interactions depending on a condition. PlantUML supports this through combined fragments, which come from the UML specification. The most common ones are:

  • alt Alternative paths (like if/else). Exactly one branch executes.
  • opt Optional path. The block runs only if a condition is true.
  • break Breaks out of the interaction if a condition is met.
  • loop Repeats a set of interactions while or until a condition holds.

These combined fragments use rectangular boxes with a label in the top-left corner. Each branch inside an alt block is separated by a dashed line. You can learn more about UML notation in our guide on UML state machine diagram notation and symbols, which covers how different UML diagrams handle state transitions and decisions.

How do you write an alt/else condition in PlantUML?

The alt keyword creates an if/else branch. Here's a basic example showing a login flow where authentication either succeeds or fails:

@startuml
actor User
participant "Auth Service" as Auth
participant Database

User -> Auth: Login request
alt credentials are valid
 Auth -> Database: Query user
 Database --> Auth: User found
 Auth --> User: 200 OK + token
else credentials are invalid
 Auth --> User: 401 Unauthorized
end
@enduml

The syntax is straightforward: write alt [condition label], describe the messages in that branch, then use else [another label] for the alternative path. Close it with end. You can have more than two branches just add more else blocks.

How do you show optional behavior with the opt keyword?

Sometimes a step only happens under certain conditions. There's no "else" it either happens or it doesn't. That's what opt is for:

@startuml
actor User
participant "API Gateway" as GW
participant "Cache" as Cache
participant "Product Service" as PS

User -> GW: GET /products/42
opt cache hit
 GW -> Cache: Check for product 42
 Cache --> GW: Return cached data
 GW --> User: 200 OK (cached)
end
alt cache miss
 GW -> PS: Fetch product 42
 PS --> GW: Product data
 GW --> User: 200 OK (fresh)
end
@enduml

This shows that the cache lookup only happens when there's a cache hit. If there's a miss, the flow falls through to the alt block. Combining opt and alt gives you fine-grained control over conditional paths.

Can you nest conditions inside other conditions?

Yes, and it's more common than you'd think in real systems. Consider an e-commerce checkout where payment processing has its own branching logic inside a larger order flow:

@startuml
actor Customer
participant "Order Service" as Order
participant "Payment Gateway" as Pay
participant "Inventory" as Inv

Customer -> Order: Place order

alt order is valid
 Order -> Inv: Check stock
 alt items in stock
 Inv --> Order: Stock confirmed
 Order -> Pay: Charge payment
 alt payment succeeds
 Pay --> Order: Payment confirmed
 Order --> Customer: Order placed (ID #1234)
 else payment fails
 Pay --> Order: Payment error
 Order --> Customer: 402 Payment failed
 end
 else out of stock
 Inv --> Order: Insufficient stock
 Order --> Customer: 409 Out of stock
 end
else order is invalid
 Order --> Customer: 400 Bad request
end
@enduml

Nested alt blocks let you model complex decision trees. Just be careful deeply nested fragments can become hard to read. If your diagram goes beyond three levels of nesting, it might be time to split it into separate diagrams or consider using a UML activity diagram for microservices architecture instead, since activity diagrams handle complex branching more naturally.

How do you loop through conditions in a sequence diagram?

The loop fragment repeats a set of messages while or until a condition is true. This is useful for retry logic, polling, or batch processing:

@startuml
participant "Client" as C
participant "Payment Service" as PS

C -> PS: Submit payment
loop retry up to 3 times
 PS -> PS: Process payment
 alt payment processed
 PS --> C: 200 OK
 else transient error
 PS --> C: 503 Retry
 C -> PS: Retry payment
 end
end
@enduml

You can also combine loop with a break condition. If the payment succeeds on the first try, the loop ends early:

@startuml
participant "Client" as C
participant "Payment Service" as PS

C -> PS: Submit payment
loop retry up to 3 times
 PS -> PS: Attempt processing
 break success
 PS --> C: 200 OK
 end
end
@enduml

What's the difference between alt, opt, break, and loop?

These four combined fragments serve distinct purposes. Here's a quick comparison:

FragmentBehaviorUML Equivalent
altMultiple branches, one executesif / else if / else
optSingle optional blockif (no else)
breakExits the enclosing interaction fragmentbreak statement
loopRepeats while/until a conditionwhile / for loop

There's also critical for regions that must complete without interruption, and par for parallel execution. But in most sequence diagrams, alt, opt, and loop cover the majority of conditional scenarios.

What mistakes do people make with conditional PlantUML code?

Here are the most common issues we've seen:

  • Forgetting the end keyword. Every alt, opt, loop, and break block must close with end. Missing it causes parse errors or garbled output.
  • Using alt when opt is more appropriate. If there's no "else" path, use opt instead. It makes the diagram cleaner and easier to understand.
  • Overcomplicating with too much nesting. Three or more levels of nested conditions become hard to follow. Consider splitting the diagram or using separate diagrams for different scenarios.
  • Vague condition labels. Writing just alt success vs. alt user has sufficient balance makes a big difference for readers. Be specific.
  • Mixing sequence diagram logic with state transitions. If your conditions represent state changes rather than message-based decisions, a state machine diagram might be a better fit. Check our reference on state machine diagram notation and symbols to decide when to use which.

Any tips for writing cleaner conditional sequence diagrams?

  1. Name your conditions like acceptance criteria. Instead of alt OK, write alt user is authenticated and has admin role.
  2. Use grouping notes to add context. PlantUML supports note blocks inside combined fragments to explain why a condition exists.
  3. Keep message arrows aligned. Only the messages relevant to a branch should appear inside the fragment. Don't put unrelated interactions in there.
  4. Use participant aliases. Long service names clutter the diagram. Alias them at the top: participant "Authentication Service" as Auth.
  5. Color-code blocks for readability. PlantUML supports #color on combined fragments: alt #LightGreen success and else #LightCoral failure.
  6. Test with small examples first. Build your conditional logic incrementally. Add one alt block, verify the output, then add the next layer.

When should you use a different UML diagram instead?

Sequence diagrams with conditional logic work well for showing how components communicate under different conditions. But they're not always the best choice:

  • If you're modeling object states and transitions, use a state machine diagram.
  • If you're modeling a business process with many branches and parallel paths, use an activity diagram.
  • If you're documenting data structures, use a class diagram.

The key question is: are you showing who talks to whom and when, or are you showing how a process flows? For the former, sequence diagrams with conditional fragments are the right tool. For the latter, activity diagrams handle complexity better, particularly in distributed systems and microservices where parallel and conditional paths intertwine.

Practical checklist before you share your conditional sequence diagram

  • Every alt, opt, loop, and break block has a matching end
  • Condition labels are specific and readable by non-developers
  • Nesting depth does not exceed three levels
  • The diagram covers at least the main success path and the most common error path
  • Participant aliases keep the diagram readable
  • You've verified the rendered output matches your intent (PlantUML's online server is useful for quick checks at plantuml.com)
  • You've considered whether the conditional logic might be better expressed in a different UML diagram type