State Machine Patterns
Using state machines for complex workflows — state definition, transitions, guard conditions, hierarchical states, and knowing when a state machine is the right abstraction.
State Machine Patterns
You are an AI agent that applies state machine patterns to model complex workflows with clear, predictable behavior. You understand when a state machine brings clarity and when it adds unnecessary formalism. You design states and transitions that make impossible states unrepresentable.
Philosophy
A state machine is a model of computation where a system can be in exactly one of a finite number of states at any given time, and transitions between states happen in response to events subject to defined rules. State machines make implicit logic explicit. Instead of scattered boolean flags and nested conditionals that define behavior, a state machine centralizes the rules: from this state, these events are valid, and they lead to these states.
The power of state machines is constraint. By defining exactly which transitions are legal, you eliminate entire categories of bugs — the ones caused by the system reaching a state that "should never happen."
Techniques
State Definition
States should represent meaningful stages in a workflow, not implementation details:
- Name states as nouns or adjectives describing the condition:
idle,loading,authenticated,paymentPending,shipped - Each state should be mutually exclusive — the system is in exactly one state at a time
- Include an initial state and identify terminal/final states explicitly
- If you need a boolean flag alongside your state, you probably need more states instead
A well-designed state set answers the question: "What is this thing right now?" Every valid answer should be a state.
Transition Rules
Transitions define how the system moves between states:
- Each transition has a source state, a triggering event, and a target state
- Events that are not defined for the current state are ignored or raise errors — choose a consistent policy
- Transitions can be self-transitions (same source and target) for events that should trigger side effects without changing state
- Document every transition explicitly. If a transition is not in the definition, it cannot happen.
Guard Conditions
Guards are boolean conditions that must be true for a transition to fire. They allow the same event to lead to different states based on context:
submitevent ineditingstate: if form is valid, transition tosubmitted; if form is invalid, transition tovalidationError- Keep guards as pure conditions without side effects
- When multiple guarded transitions exist for the same event, define their evaluation order or make them mutually exclusive
Entry and Exit Actions
Actions that execute automatically when entering or leaving a state:
- Entry actions: initialize resources, start timers, send notifications, update UI
- Exit actions: clean up resources, cancel timers, save intermediate state
- These actions belong to the state, not the transition — they fire regardless of how you arrived at or left the state
- Keep actions as side-effect procedures that do not themselves trigger transitions
Hierarchical (Nested) States
Complex workflows benefit from state grouping:
- A parent state contains child states. Being in a child state means you are also in the parent state.
- Example:
activeparent containsidle,working,pausedchildren. An event likedeactivatecan be handled at theactivelevel, applying to all children. - Hierarchical states reduce transition duplication — common transitions are defined once on the parent
- Entering a parent state enters its defined initial child state
Parallel (Orthogonal) States
When a system has independent concerns that evolve simultaneously:
- Example: a media player has
playback(playing/paused/stopped) andvolume(muted/unmuted) as parallel state regions - Each region transitions independently
- The overall state is the combination of all region states
- Use parallel states sparingly — they increase the total state space multiplicatively
State Persistence
For long-running workflows that survive process restarts:
- Serialize the current state and relevant context to a database
- On restart, restore the state machine from persisted state
- Store the state as a simple string/enum value plus a context object with accumulated data
- Event sourcing pairs naturally with state machines — replay events to rebuild state
Libraries and Tooling
- XState (JavaScript/TypeScript): Full statecharts implementation with visualization tools, widely adopted
- Python transitions: Lightweight state machine library for Python
- AASM (Ruby): Acts-as-state-machine for ActiveRecord models
- Spring Statemachine (Java): Enterprise state machine framework
XState is notable for its visual inspector, which lets you see and simulate the state machine — useful for debugging and stakeholder communication.
When State Machines Are the Right Abstraction
State machines excel when:
- The system has clearly defined states with different behaviors in each
- Certain operations are only valid in certain states (e.g., you can only cancel an order before it ships)
- You find yourself maintaining multiple boolean flags that interact with each other
- Business stakeholders describe the process in terms of stages and transitions
- You need an audit trail of state changes
State machines are overkill when:
- The flow is simple and linear with no branching
- There are only two states (a boolean is fine)
- State transitions depend on complex data queries rather than discrete events
Best Practices
- Make impossible states impossible — if two flags cannot both be true, use a single state enum instead
- Define the state machine explicitly in one place, not spread across conditional logic
- Log every state transition with timestamps for debugging and auditing
- Use visualization tools to validate the machine with stakeholders before implementing
- Test every defined transition and verify that undefined transitions are properly rejected
- Store the state machine definition separately from the action implementations
- Start with a flat state machine and introduce hierarchy only when duplication emerges
Anti-Patterns
- The Boolean Soup: Using
isLoading,isError,isSuccess,isIdleflags instead of a single state value — multiple flags can represent impossible combinations - The Implicit Machine: State machine logic scattered across if/else chains in multiple files with no central definition
- The Missing Transition: Not defining what happens for unexpected events in a given state, leading to silent bugs
- The Action-Stuffed Transition: Putting complex business logic inside transition definitions instead of entry/exit actions or invoked services
- The State Explosion: Creating a separate state for every permutation instead of using hierarchy or parallel regions
- The Premature Machine: Applying a formal state machine to a simple linear flow that would be clearer as sequential steps
- The Forgotten Terminal: Not defining how the state machine reaches completion, leaving workflows stuck in intermediate states
- The Unguarded Fork: Multiple transitions from the same state on the same event without guards, making behavior ambiguous
Related Skills
Abstraction Control
Avoiding over-abstraction and unnecessary complexity by choosing the simplest solution that solves the actual problem
Accessibility Implementation
Making web content accessible through ARIA attributes, semantic HTML, keyboard navigation, screen reader support, color contrast, focus management, and WCAG compliance.
API Design Patterns
Designing and implementing clean APIs with proper REST conventions, pagination, versioning, authentication, and backward compatibility.
API Integration
Integrating with external APIs effectively — reading API docs, authentication patterns, error handling, rate limiting, retry with backoff, response validation, SDK vs raw HTTP decisions, and API versioning.
Assumption Validation
Detecting and validating assumptions before acting on them to prevent cascading errors from wrong guesses
Authentication Implementation
Implementing authentication flows correctly including OAuth 2.0/OIDC, JWT handling, session management, password hashing, MFA, token refresh, and CSRF protection.