Loading learning content...
Class diagrams reveal the static architecture of a system—what entities exist and how they relate. But software is fundamentally dynamic: users click buttons, data flows through pipelines, transactions traverse multiple services, and business rules orchestrate complex sequences of actions.
To capture this dynamism, we need diagrams that model flow—the sequence of activities, the branching of decisions, the parallelism of concurrent operations. Activity Diagrams serve precisely this purpose: they are UML's answer to flowcharts, but with rigorously defined semantics and powerful constructs for modeling real-world complexity.
By the end of this page, you will understand the complete vocabulary of Activity Diagrams—from basic actions and control flows to advanced constructs like fork/join for concurrency, swimlanes for responsibility assignment, and object flows for data movement. You'll be able to model business processes, use cases, and algorithmic logic with professional precision.
An Activity Diagram is a UML behavioral diagram that models the flow of control and data through a sequence of actions. Unlike sequence diagrams that focus on message passing between objects, activity diagrams emphasize the procedural logic—what happens, in what order, under what conditions, and potentially in parallel.
Historical Context:
Activity diagrams evolved from several predecessors:
UML Activity Diagrams synthesize these influences into a standardized notation with formal semantics, making them suitable for everything from high-level business process modeling to detailed algorithm specification.
While superficially similar, UML Activity Diagrams offer crucial advantages over informal flowcharts: standardized notation understood globally, formal semantics enabling tool support, explicit concurrency modeling with fork/join, object flow modeling, and swimlanes for organizational responsibility. When precision matters, choose Activity Diagrams.
Activity diagrams use a carefully designed set of symbols, each with precise semantics. Mastering this vocabulary is essential for creating unambiguous, professional diagrams.
Initial and Final Nodes:
Every activity must have a defined beginning and end:
The distinction between Activity Final and Flow Final is crucial: Activity Final is like System.exit() while Flow Final is like a single thread completing.
| Symbol | Name | Purpose | Visual Representation |
|---|---|---|---|
| ● | Initial Node | Starting point(s) of the activity | Filled black circle |
| ◉ | Activity Final | Terminates entire activity | Circle with inner filled circle |
| ⊗ | Flow Final | Terminates one flow path only | Circle with X inside |
| ▭ | Action | An atomic, non-decomposable step | Rounded rectangle |
| → | Control Flow | Sequence from one node to next | Arrow connecting nodes |
| ◇ | Decision Node | Branching based on condition | Diamond (hollow) |
| ◇ | Merge Node | Rejoins alternative paths | Diamond (hollow) |
| ▬ | Fork | Splits into concurrent flows | Heavy horizontal bar |
| ▬ | Join | Synchronizes concurrent flows | Heavy horizontal bar |
Actions:
Actions are the atomic units of behavior in an activity diagram—the actual work being done. They are represented as rounded rectangles with a brief description of the action inside.
Well-written action names:
Poorly-written action names:
The right level of granularity depends on your audience. For business stakeholders, actions might be 'Approve Loan Application'. For developers implementing the feature, you might decompose this into 'Check Credit Score', 'Verify Employment', 'Calculate Risk Rating', 'Make Approval Decision'. Choose granularity that communicates effectively without overwhelming.
Control flow represents the sequencing of actions—what happens after what, under what conditions. This is the backbone of any activity diagram.
Sequential Flow:
The simplest control flow is a direct arrow from one action to another, indicating that when the first action completes, the second begins. This models straightforward procedural logic:
[Receive Order] → [Validate Order] → [Process Payment] → [Ship Order]
Decision Nodes (Branching):
Real processes involve decisions. Decision nodes are diamonds with one incoming flow and multiple outgoing flows, each labeled with a guard condition in square brackets.
[Validate Order] → ◇ Decision
├── [valid] → [Process Payment]
└── [invalid] → [Reject Order]
Critical Rules for Decision Nodes:
[else] guard)[orderTotal > 100] are clearer than [else] when possible[customer is preferred] not [customer.loyaltyPoints > 1000]Merge Nodes (Rejoining):
Merge nodes are the counterpart to decision nodes—they bring multiple alternative paths back together. A merge node is also a diamond, but with multiple incoming flows and one outgoing flow.
[Process Payment] → ◇ Merge ←── [Apply Store Credit]
↓
[Ship Order]
Important Distinction:
A merge node is not a synchronization point. It simply combines alternative flows. If flows from a decision node eventually rejoin, use a merge. If parallel flows from a fork need to synchronize, use a join (covered in the concurrency section).
Loops:
Loops are modeled using decision and merge nodes together—a flow that circles back:
◇ Merge → [Process Item] → ◇ Decision
↑ ├── [more items] → Merge
└────────────────────────────┘
└── [no more items] → [Complete Order]
This structure models iteration: keep processing items until none remain.
A frequent error is using a merge node where a join is needed. Merge combines mutually exclusive alternative paths (only one flow arrives). Join synchronizes concurrent paths (waits for all flows to arrive). Using merge for concurrent flows creates a race condition where whichever path finishes first continues execution—usually not the intended behavior.
One of the most powerful features of Activity Diagrams is their ability to model concurrent execution—multiple activities happening in parallel. This is essential for modeling real-world processes where independent tasks can proceed simultaneously.
Fork Nodes:
A fork node splits a single flow into multiple concurrent flows. It is represented as a thick horizontal (or vertical) bar with one incoming edge and multiple outgoing edges.
[Receive Order] → ▬ Fork
├→ [Check Inventory]
├→ [Validate Payment]
└→ [Verify Shipping Address]
After the fork, all three activities begin execution concurrently. They may complete in any order and run at different speeds.
Join Nodes:
A join node is the synchronization counterpart to fork. It waits for all incoming concurrent flows to complete before proceeding. Represented as a thick bar with multiple incoming edges and one outgoing edge.
[Check Inventory] ──→
[Validate Payment] ──→ ▬ Join → [Fulfill Order]
[Verify Address] ────→
The [Fulfill Order] action only begins once all three parallel activities have completed.
Interleaved Concurrency Patterns:
Real-world processes often combine sequential and concurrent sections:
● → [Receive Order] → ▬ Fork
├→ [Check Inventory] → Merge → ▬ Join → [Pack Order] → ▬ Fork
└→ [Process Payment] → ─────────┘ ├→ [Generate Invoice]
└→ [Update Tracking]
↓
▬ Join → [Ship Order] → ◉
This diagram models: receive order, then concurrently check inventory and process payment, synchronize, pack order, then concurrently generate invoice and update tracking, synchronize, finally ship.
Conditional Concurrency:
Sometimes parallel branches are conditional. You can combine decisions with forks:
◇ Decision → [express shipping] → ▬ Fork (express path with parallel steps)
└→ [standard shipping] → [Standard Processing]
Or certain parallel branches may only execute conditionally:
▬ Fork → [Always Do This]
→ ◇ Decision → [condition met] → [Optional Parallel Task] → Join
→ [else] → ───────────────────────────────────→
When modeling concurrent activities for software design, consider not just logical independence but also resource contention. Database transactions, file locks, network bandwidth, and CPU cores all constrain practical parallelism. Activity diagrams show logical concurrency; implementation must address physical concurrency constraints.
When modeling cross-functional processes, it's crucial to show who is responsible for each action. Swimlanes (formally called Activity Partitions in UML) divide the activity diagram into vertical or horizontal bands, each representing a participant—a role, department, system, or actor.
Visual Structure:
┌─────────────────────────────────────────────────────────────────┐
│ Customer │ Order System │ Warehouse │
├──────────────────┼────────────────────┼────────────────────────┤
│ │ │ │
│ [Place Order] ──│──→ [Validate] ─────│──→ [Reserve Stock] │
│ │ ↓ │ │
│ │ [Process Pay] ──│──→ [Pack Order] │
│ │ │ ↓ │
│ [Receive] ←─────│────────────────────│──── [Ship] │
│ │ │ │
└─────────────────────────────────────────────────────────────────┘
Actions are placed within the swimlane of the responsible party. Arrows crossing swimlane boundaries represent handoffs between participants.
Multi-Dimensional Swimlanes:
UML allows nested partitions for complex organizational modeling:
┌─────────────────────────────────────────────────────────────────┐
│ Organization │
├───────────────────────────────┬─────────────────────────────────┤
│ Frontend │ Backend │
├───────────────┬───────────────┼───────────────┬─────────────────┤
│ UI Component │ State Manager │ API Gateway │ Database │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ │ │ │ │
│ [Render] │ [Update] │ [Route] │ [Query] │
│ │ │ │ │
└───────────────┴───────────────┴───────────────┴─────────────────┘
This two-level hierarchy partitions first by frontend/backend, then by specific component. Use this technique sparingly—complexity escalates quickly.
Swimlane Benefits:
For microservice architectures, swimlanes naturally map to service boundaries. Each service gets a lane, and cross-lane arrows represent inter-service communication. This makes activity diagrams excellent for modeling saga patterns, distributed transactions, and service choreography.
So far, we've focused on control flow—the sequencing of activities. But real processes also involve data flow—objects being created, transformed, and consumed. Activity diagrams support explicit modeling of data through Object Nodes and Object Flows.
Object Nodes:
An object node represents a data object at a particular point in the workflow. It is drawn as a rectangle (not rounded) with the object name and optionally its state:
[Create Order] → ┌─────────────┐ → [Validate Order] → ┌───────────────────┐
│ Order │ │ Order [validated] │
│ [created] │ └───────────────────┘
└─────────────┘
The state notation [created], [validated] shows the object's condition at that point in the flow.
Object Flows:
Object flows are edges connecting actions to object nodes, showing data production and consumption:
| Pattern | Meaning | Example |
|---|---|---|
| Action → Object | Action produces an output | [Calculate Tax] → [Tax Amount] |
| Object → Action | Action requires an input | [Customer Data] → [Verify Identity] |
| Object → Object | Data transformation | [Raw Order] → [Validated Order] |
| Action → Object → Action | Data flows between actions | [A] → [Data] → [B] |
| Fork with Object | Same data used by parallel actions | [Order] → Fork → multiple consumers |
Pins:
For complex actions with multiple inputs and outputs, UML provides pins—small rectangles attached to action boundaries:
┌────────────────────────┐
[Customer]──│→ →│──[Receipt]
│ Process Purchase │
[Products]──│→ →│──[Shipment]
└────────────────────────┘
Pins explicitly name the inputs and outputs of an action, making data dependencies crystal clear.
Data Stores and Buffers:
Data Store: Persistent storage represented by a rectangle with the stereotype «datastore». Data written to a data store persists and can be read by subsequent activities:
[Save Order] → «datastore» Order Database → [Generate Report]
Central Buffer: A temporary holding area for objects between actions, useful when production and consumption rates differ:
[Produce Items] → «centralBuffer» Item Queue → [Package Items]
Not every diagram needs explicit object flows. Include them when: (1) data transformations are the focus, (2) data dependencies aren't obvious from action names, (3) intermediate data states are important, or (4) you're modeling data pipelines or ETL processes. For simpler workflows, control flow alone may suffice.
Beyond the fundamental elements, UML Activity Diagrams provide several advanced constructs for modeling complex scenarios.
Expansion Regions:
When an action must be performed for each item in a collection, use an expansion region—a dashed rectangle containing the iterated actions with input/output expansion nodes:
┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
╎ «iterative» ╎
╎ ╎
╎ [order items] → [Validate] → [validated] →╎
╎ ↓ ╎
╎ [Calculate Price] ╎
└╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┘
Modes include:
Interruptible Activity Region:
Some activities can be interrupted by events. An interruptible region is shown with a dashed rounded rectangle, with an interrupting edge (lightning bolt arrow) showing what can interrupt and where control goes:
┌─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┐
│ │
│ [Process Long Task] │──⚡──→ [Handle Cancellation]
│ │
└─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┘
↑
[User Cancel] (Accept Event)
This models scenarios like user cancellation, timeout handling, or exception flows.
Call Behavior Action:
When an action is complex enough to warrant its own activity diagram, use a call behavior action—depicted as an action with a small fork symbol (⋔) in the corner, indicating it invokes another activity:
[Receive Order] → [Process Order ⋔] → [Ship Order]
↓
(links to Order Processing
Activity Diagram)
This supports hierarchical decomposition—keeping top-level diagrams simple while allowing drill-down into details.
Exception Handlers:
For modeling error handling, activity diagrams support exception handlers:
┌─────────────────────────┐
│ [Process Payment] │──⚠──→ [Handle Payment Error]
│ │
└─────────────────────────┘
The zigzag arrow indicates exception flow, and the target action handles the error condition.
While UML provides these advanced constructs, not all tools support them equally, and not all audiences understand them. Use advanced features when they genuinely improve clarity or when your tooling and team require the precision. For many practical purposes, basic actions, decisions, forks/joins, and swimlanes cover 90%+ of needs.
Creating activity diagrams that communicate effectively requires both technical correctness and design sensibility. Here's a systematic approach:
Step 1: Define Scope and Audience
Before drawing anything, clarify:
Step 2: Identify Key Elements
List out:
Step 3: Draft and Iterate
Sketch a rough draft, then refine:
Step 4: Validate with Stakeholders
Diagrams are communication tools. Validate with your audience:
A well-designed activity diagram should allow someone unfamiliar with the process to understand the flow within a few minutes of study. If extensive verbal explanation is required, the diagram needs simplification or restructuring.
Activity diagrams are powerful tools for modeling dynamic behavior—the flow of control and data through processes, algorithms, and use cases. Let's consolidate the essential concepts:
What's Next:
While activity diagrams excel at modeling workflows and processes, they don't capture every aspect of dynamic behavior. For modeling how an object transitions between states over its lifetime—responding to events and triggers—we need State Diagrams. The next page provides a comprehensive exploration of state machine modeling.
You now have a thorough understanding of UML Activity Diagrams—their notation, semantics, and practical application. You can model business processes, use cases, and algorithms with the same professional precision used by experienced software architects. Next, we'll explore State Diagrams for modeling object lifecycles.