You might have heard of “state machine” or “finite-state machine” before. If you look up state machine on Wikipedia, you’ll read that a state machine is described as a “mathematical model of computation,” followed by a bunch of symbols and computer science jargon that doesn’t immediately seem to apply to your team’s work.
However, state machines are really useful for describing almost any kind of logic, feature, user story, sequence, process, workflow, specification, and more. They can greatly improve how your team collaborates on processes, flows, features, and any other kinds of application logic, and they’re much simpler to understand than you may think.
If you’ve worked with flowcharts or diagrammed a process on a whiteboard with boxes and arrows, you may already know how state machines work!
A state machine is a way of modeling how something works, using states and transitions to show how something changes over time in response to events.
Specifically, it formally models how a system transitions from one state to another based on specific events (e.g., triggers, signals, changes, etc.). Think of it as a useful tool for visualizing and designing the flow of user experiences, product features, or any process you’re working on.
Visually, state machine diagrams are similar to flowcharts. Both use shapes to represent states (e.g., steps in a flow) and arrows to indicate transitions between those states. The main difference is that state machines are more precise, formal, and powerful than flowcharts. They’re also more flexible since you can use them to model any kind of logic, not just processes.
State machines are a concept deeply rooted in computer science; however, they have broad applications that extend to various business domains and design disciplines. From developing intuitive software interfaces to designing effective business processes, state machines provide a structured way to model and understand complex systems. Whether you’re a product owner, project manager, designer, developer, QA tester, business analyst, or any other role, understanding state machines can significantly improve your ability to design, manage, and refine features, processes, and products.
In short, a state machine lets us clearly understand how something reacts when an event occurs.
The parts of a state machine​
Visually, state machines are just boxes and arrows. The building blocks of a state machine – states, events, and transitions, are quite straightforward (no pun intended), but together, they form a powerful tool for modeling and understanding systems.
States​
A state represents a particular situation, mode, or status that something can be in. For instance, an e-commerce site’s order can be in the Pending, Shipped, Delivered, or Returned states. Each of these is a finite state, contributing to the entire lifecycle of an order.
Finite states are deterministic, meaning that something can only be in exactly one finite state at a time. An order cannot be in both the Pending and Delivered states at the same time, just like you can’t be in both the Asleep and Awake states simultaneously.
State machines always start at an initial state and may end up in a final state, indicating that the state machine is “done” and can no longer transition to any other state.
Events​
Events are occurrences; they’re a record that something happened. Using the previous example, an event like item shipped might transition an order’s state from Pending to Shipped.
Transitions​
A state transition describes how a system “moves” from one state to another. These are the arrows between the states, labeled by the event that causes the transition to occur.
In state machines, transitions always happen immediately. For example, an order can be Pending for some time (almost frustratingly so), but when the item shipped event occurs, it immediately transitions to the Shipped state.
View this state machine in Stately.
A state machine example​
Let’s say you wanted to create a flow for a travel booking app. This flow represents the logic of a user booking a flight, hotel, and rental car, and you can apply this logic to the frontend code (as a multi-step flow) and backend code (as a workflow that communicates with APIs to book everything). Let’s model this travel booking flow as a state machine.
First, think of all of the states of this flow. Each state represents something that is happening, such as the flight or hotel being booked:
- Booking flight
- Booking hotel
- Booking car
- Confirmation
- Error
Tip: make sure to handle errors! In the real world, things don’t always go according to plan.
Then, think of all the events that can happen in the flow. There are the “happy-path” events:
- Flight booked
- Hotel booked
- Car booked
But other events can happen:
- Flight booking failed
- Hotel booking failed
- Car booking failed
- Timeout
You can then combine these states and events to create a complete state machine diagram that represents all the possible user flows through the app:
The state machine above uses parent and child states, a feature of statecharts, to reduce complexity.
These state machines serve as a source of truth for your app logic since you can use them for:
- Documentation that outlines the features and use cases represented in the flow
- Code you can generate from the state machine
- Diagrams as visual documentation
- Tests you can also generate for various flows
Benefits of using state machines​
Understanding and managing anything that can happen in your applications is crucial for efficient collaboration and innovation – you want to ensure that your team can understand and iterate on app logic and features quickly, no matter how complex they get. State machines are a powerful visual approach for accomplishing that, and they’re much more than just a diagramming tool.
There are many key advantages of using state machines:
Visualized documentation​
With state machine diagrams, you can visually represent the states of a process, making it easier to grasp and communicate complex logic. These diagrams bridge the communication gap between technical and non-technical team members. They also provide a clear way to document and share app logic, which you could use for onboarding new team members. After all, following boxes and arrows (just like a flowchart) is much easier than parsing code, especially for someone unfamiliar with the codebase.
Our export to Mermaid feature enables you to embed your state machines in GitHub and GitLab pull requests and comments.
Consistent, robust application logic​
By mapping out all states and transitions, state machines ensure you account for every possible scenario. This minimizes unexpected behaviors (such as undesired states/transitions) and system inconsistencies because it is mathematically impossible for a state machine to take a transition that does not exist. You can quickly identify a transition to a state that should not go to that state. This is especially useful for complex apps, where it’s easy to miss edge cases or unexpected scenarios.
Modularity and scalability​
State machines allow for isolating logic, meaning you can make changes or additions to a specific segment without overhauling the entire system. Regardless of framework, programming language, or implementation, the core abstractions remain the same: states, events, and transitions. If you need to add, change, or remove a feature, the process is to add, change, or remove states and transitions.
Test path generation​
State machines clearly define all possible states, events, and transitions, allowing testers to simulate specific events and verify if transitions to specific states occur as expected. Since state machines are directed graphs, they act like a “map” for your app logic. This map enables the automatic generation of many different “paths” through the state machine. Each path represents a potential use case, even those that may initially go unnoticed, such as edge cases. Exhaustive test path generation is also possible so that you can test every possible path through the state machine.
Transition to state machines​
We love state machines at Stately because we know how valuable they can be to development teams. State machines provide a visually clear way to understand, design, and manage flows and logic at any level of complexity. Integrating the principles of state machines can lead to more predictable outcomes, clearer communication, and enhanced efficiency for the entire team, from project managers to designers and developers. You can use them as a precise way of diagramming and documenting app logic and even use them in your codebase to power that same logic.
There are many ways to get started with state machines:
- Watch our video intro to Stately.
- Learn about generating state machines from text descriptions with our AI feature.
- Read more about using XState, our open-source library for state machines anywhere JavaScript is supported.
- Jump into creating your own machine in our drag-and-drop editor at state.new.