If you've ever tried to model how an object changes behavior based on events or conditions, you've likely run into UML state machine diagrams. But understanding the actual notation the shapes, arrows, labels, and special symbols can feel confusing, especially when different tools and textbooks show them slightly differently. Knowing the correct state machine diagram symbols and how to use them helps you communicate system behavior clearly to your team, avoid misinterpretation during development, and document reactive systems accurately.
What Is a UML State Machine Diagram?
A UML state machine diagram (sometimes called a statechart diagram) shows the different states an object can be in, what causes it to transition between those states, and what actions occur during those transitions. It's part of the Unified Modeling Language standard maintained by the Object Management Group (OMG). Engineers use these diagrams to model reactive objects things that respond to events like user input, sensor readings, messages, or timers.
Unlike a UML class diagram that shows static structure, a state machine diagram captures dynamic behavior over time. It answers the question: given the current state and an incoming event, what happens next?
What Are the Core Symbols in a State Machine Diagram?
Every UML state machine diagram uses a small set of standard notations. Here's what each one means:
States
A state is drawn as a rectangle with rounded corners. Inside, you write the state name. States represent a condition or situation during the object's lifetime where it satisfies some condition, performs some activity, or waits for an event.
Example state names: Idle, Processing, Error, WaitingForResponse.
Initial Pseudo-State
The initial state is a small filled black circle, typically in the top-left area of the diagram. It has one outgoing transition arrow leading to the first real state. Every state machine must have exactly one initial state.
Final State
The final state is a circle with a filled black circle inside it (like a bullseye). It indicates that the object has completed its lifecycle within that state machine. A diagram can have more than one final state.
Transitions
A transition is a solid arrow connecting two states. The arrow points from the source state to the target state. Transitions are labeled with a string following this format:
event [guard] / action
- Event the trigger that causes the transition (e.g., submit, timeout, userClick)
- Guard condition (optional) a boolean expression in square brackets that must be true for the transition to fire (e.g., [isValid])
- Action (optional) behavior that executes when the transition occurs (e.g., /saveData, /logError)
You won't always use all three parts. A simple arrow labeled just start or submit is perfectly valid.
Self-Transitions
A self-transition is an arrow that loops from a state back to itself. This means an event occurs while the object is in that state, the action runs, but the object stays in the same state.
What Are the Advanced Notations?
Once you're comfortable with the basics, you'll encounter more specialized symbols in complex diagrams.
Composite States (Hierarchical States)
A composite state is a state that contains nested sub-states drawn inside it. You draw it as a larger rounded rectangle with an interior region (often separated by a dashed line) that contains its own state machine. This lets you group related states and share common transitions at the parent level.
For example, a composite state Active might contain sub-states Running and Paused. A transition out of Active applies to both sub-states without needing duplicate arrows.
Fork and Join Pseudo-States
A fork is a short thick horizontal or vertical bar that splits one transition into multiple concurrent transitions. A join is the same bar that merges multiple concurrent transitions into one. Forks and joins are used when an object enters or exits parallel (concurrent) regions.
Choice Pseudo-State
A choice pseudo-state is drawn as a diamond shape. An incoming transition arrives at the diamond, and multiple outgoing transitions each have guard conditions. The system evaluates the guards and picks the first one that's true. This models if/else branching logic.
Junction Pseudo-State
A junction pseudo-state looks like a small filled circle (solid black dot, smaller than the initial state circle). It chains multiple transitions together. Unlike choice, junction transitions are evaluated as a single compound transition, which matters for complex guard logic.
History Pseudo-State
A shallow history is shown as a circle with the letter H inside. A deep history is a circle with H. These let a composite state remember which sub-state it was last in. When a transition targets the history state, the object re-enters the previous sub-state instead of starting from the default initial state.
Entry, Do, and Exit Actions
States can have three kinds of internal behavior listed in compartments inside the rounded rectangle:
- entry / action runs once when the state is entered
- do / activity runs continuously while in the state (can be interrupted by a transition)
- exit / action runs once when the state is exited
You write these on separate lines inside the state box, separated by dashed lines.
Deferred Events
You can list events with the keyword defer inside a state. This means the event is queued and not processed until the object transitions to a state that can handle it. You write it as event / defer.
What Does a Simple Example Look Like?
Consider an order in an e-commerce system:
- Initial state (filled circle) → transitions to Created
- Created → labeled submitOrder [cartNotEmpty] / processPayment → Processing
- Processing → labeled paymentSuccess → Shipped
- Processing → labeled paymentFailed → Cancelled
- Shipped → labeled delivered → Completed (final state)
Each state could have entry actions like entry / sendConfirmationEmail and exit actions like entry / logStateChange.
When you need to model sequences of interactions alongside state changes, a sequence diagram with conditional logic can complement your state machine by showing the message flow between objects.
When Should You Use a State Machine Diagram?
Use these diagrams when:
- An object's behavior changes significantly depending on its current state
- There are clear events or triggers that move the object between states
- You need to design or verify protocol behavior (e.g., TCP connections, authentication flows)
- You're building UI workflows, game logic, or embedded system firmware
- You want to identify unreachable states or missing event handlers before coding
You probably don't need one for simple data objects that have no meaningful state-dependent behavior.
What Common Mistakes Do People Make?
Forgetting the initial state. Every state machine diagram needs exactly one initial pseudo-state. Without it, the reader doesn't know where the lifecycle begins.
Leaving transitions unlabeled. Unlabeled arrows force the reader to guess what triggers the transition. Even if the event is obvious, label it.
Using states for actions. A state is a condition that persists over time, not a momentary action. If something happens instantly, it belongs on a transition arrow, not in a state box.
Overloading one diagram. If your diagram has 30+ states, consider breaking it into composite states or separate diagrams per subsystem.
Mixing up guard conditions and events. The event is what happens. The guard condition is a test. Writing [timeout] when you mean timeout as an event changes the semantics.
Ignoring entry and exit actions. These are powerful for avoiding duplicate logic. If multiple transitions lead to the same state and all need to run the same setup code, put it in the entry action instead of repeating it on each transition.
How Does This Compare to Other Diagram Notations?
State machine diagrams focus on a single object's lifecycle. If you need to show how multiple objects or components interact, a component diagram or interaction diagram is more appropriate. The notations serve different purposes, and experienced engineers use them together to cover both structure and behavior.
For reference, the official UML specification is published by the Object Management Group (OMG).
Quick Tips for Drawing Clear State Machine Diagrams
- Place the initial state in the top-left corner and the final state in the bottom-right.
- Aim for 5–15 states per diagram. If you have more, use composite states.
- Always label every transition with at least the triggering event.
- Use consistent naming: verb phrases for events, adjective or noun phrases for state names.
- Draw the "happy path" (most common flow) as the primary left-to-right or top-to-bottom flow.
- Use tools like PlantUML or Mermaid to keep diagrams version-controlled and easy to update alongside your code.
Checklist: Validate Your State Machine Diagram
- Does it have exactly one initial state (filled circle)?
- Is every transition labeled with at least an event name?
- Are guard conditions in square brackets and actions after a forward slash?
- Does every state that needs setup or cleanup logic use entry/exit actions?
- Have you checked for unreachable states (no incoming transitions)?
- Have you checked for dead-end states (no outgoing transitions and no final state marker)?
- Is the diagram readable at a glance under 15 states, with logical flow direction?
- Did you use composite states or history pseudo-states to reduce visual clutter?
Start by sketching your object's states on paper, listing the events that matter, and drawing arrows between them. Then apply the standard notation. Getting the symbols right from the start saves hours of confusion during code reviews and implementation.
Uml Class Diagram Syntax Reference Guide for Software Engineers
Mermaid Uml Component Diagram Syntax Guide
Uml Activity Diagram Syntax for Microservices Architecture
Plantuml Sequence Diagram Code Examples with Conditional Logic
How to Write Flowchart Code From Scratch: a Complete Beginner's Tutorial
Mermaid Flowchart Syntax Examples for Github Repositories