Skip to main content

Sequence diagram

In what order do these participants talk to each other, for one specific scenario? Where a class diagram shows what can happen, a sequence diagram shows what does happen, in order, for one concrete run through the system. It is the only one of the five UML diagrams on this site that has a time axis.

Lifelines and activation bars

Every participant - an object, a class, an actor - gets a box at the top and a lifeline: a dashed vertical line running down the page, standing in for "this participant exists, for the duration of this diagram." Time runs top to bottom; nothing about horizontal position carries meaning.

An activation bar (also called an execution bar) is the thin solid rectangle drawn on top of a lifeline while that participant is actively doing work - inside a method call, not idle. A participant can be activated more than once across a diagram, and one activation can nest another if it makes a call of its own mid-work.

LoginFormlifeline (dashed)activation bar
The dashed line is always there. The solid bar only appears while this participant is doing work.

Message types: synchronous, asynchronous, return

Three arrow styles, and mixing them up is the single most common sequence-diagram mistake - the arrowhead is the entire signal for whether the caller waits:

login(user, pass)synchronous - caller blockslogAttempt(user)asynchronous - fire and move onsession tokenreturn - dashed, flows back
Solid + filled = synchronous. Solid + open = asynchronous. Dashed + open = a return.

A synchronous call's activation bar on the caller pauses for the entire duration of the callee's own activation - that pause is what "the caller blocks" looks like on the diagram. An asynchronous call has no such pause: the caller's bar keeps going right past it.

Self-calls

A participant can call its own method - drawn as a short loop out from the lifeline and back, with its own small activation bar layered on top of the caller's.

AuthServicehash(pass)
A self-call: AuthService calling its own private hash() method mid-work.

Combined fragments: alt, opt, loop, par

A plain sequence of arrows can only describe one straight-line path through a scenario. Combined fragments are what let a sequence diagram express branching, optionality and repetition without leaving the notation - this is the part most explanations skip, and the part that makes the diagram actually expressive instead of merely decorative:

  • alt (alternative) - if/else. One or more labeled sections stacked in a frame, separated by dashed lines, each with a [guard] condition; exactly one section executes per run, whichever guard is true.
  • opt (optional) - a single section that runs only if its [guard] holds, otherwise it is skipped entirely. Equivalent to an alt with only one branch and an implicit "do nothing" else.
  • loop - the wrapped messages repeat as a group for as long as the [guard] holds, or a fixed count (loop 3, say).
  • par (parallel) - two or more sections, separated by dashed lines, that execute concurrently rather than in sequence.
alt[credentials valid]createSession()[credentials invalid]error
Exactly one of these two sections runs per login attempt - the notation for an if/else without leaving the sequence diagram.

The login flow, built up in stages

Stage 1 - the straight-line happy path. Four participants, no branching yet - this is the diagram from the class diagram page's Stage 4, now shown as a single scenario instead of a static structure.

UserLoginFormAuthServiceDatabasesubmit(user, pass)login(user, pass)findUser(name)user recordsession token

Stage 2 - branch on the result. Wrap the tail end in alt: a found user leads to a session; a missing one returns an error instead. The straight line becomes two possible straight lines, exactly one of which runs per attempt.

UserLoginFormAuthServiceDatabasesubmit(user, pass)login(user, pass)findUser(name)user or nullalt[user found]session token[user not found]error

Two stages, and the diagram now shows what happens on every login attempt, not just the one where everything works - which is usually the version an interviewer actually wants to see.

When to reach for it: one specific interaction where the order or timing of messages is the point - a cache miss that has to fall through to a slower store, a retry loop, a callback that arrives out of order. When not to bother: a single method calling a single getter. If the arrows would just restate the call stack with no interesting ordering or branching, skip the lifelines and say it in a sentence.

Common mistakes

  • Using a synchronous arrow for a fire-and-forget call. If the caller does not actually wait, an open arrowhead says so; a filled arrowhead implies a block that never happens, and misleads anyone reasoning about latency from the diagram.
  • Skipping activation bars entirely. Without them, a return message and a fresh call look identical - the bars are what make "this participant is mid-work" a visible fact instead of something the reader has to infer from arrow order.
  • Flattening real branching into one straight-line path. A sequence diagram that only shows the happy path answers a narrower question than the one usually being asked; alt and opt exist specifically so branching does not require a second diagram.
  • Drawing par for things that are not actually concurrent. Two calls that must happen in a specific order are not parallel just because they are both "fast" - reserve par for genuinely independent work, like firing an email and writing an audit log at the same time.

Try it yourself: extend the Stage 2 diagram above with a loop fragment around the whole alt block, capped at three attempts, to model "let the user retry a failed login up to three times before locking the account." Where does the loop's guard condition live, and what happens to the diagram once the count is exceeded?

Check yourself

Question 1 of 4

A message arrow is solid with a filled (solid) arrowhead. What kind of message is it?