Model a business process as a set of defined states with explicit transitions between them. Unlike linear workflows, items can move forwards, backwards, and loop — matching how real business processes actually behave.
Rendering diagram…
Use a state machine when:
Rendering diagram…
Map every possible state and every valid transition:
| Current State | Action | Next State | Who Can Act | Side Effects |
|---|---|---|---|---|
| Draft | Submit | In Review | Author | Notify reviewer |
| In Review | Approve | Approved | Reviewer | Notify author |
| In Review | Reject | Draft | Reviewer | Notify author with feedback |
| In Review | Request Changes | Draft | Reviewer | Notify author with specific items |
| Approved | Publish | Published | Editor | Publish to website |
| Approved | Revoke | Draft | Manager | Notify all parties |
| Published | Archive | Archived | Admin | Remove from website |
| Published | Unpublish | Approved | Editor | Remove from website, keep approved |
| Any | Cancel | Cancelled | Author + Manager | Notify all parties |
The core loop:
WHILE state != terminal_state:
valid_actions = get_valid_transitions(current_state, current_user_role)
display_task(item, valid_actions)
chosen_action = wait_for_user_response()
IF chosen_action IN valid_actions:
execute_side_effects(current_state, chosen_action)
current_state = transition_table[current_state][chosen_action]
log_transition(old_state, chosen_action, new_state, user, timestamp)
ELSE:
reject_invalid_action()
Don't hardcode transitions in the workflow. Store them in a list or database:
| From State | Action | To State | Allowed Roles | Enabled |
|---|---|---|---|---|
| draft | submit | in-review | author | Yes |
| in-review | approve | approved | reviewer,manager | Yes |
| in-review | reject | draft | reviewer,manager | Yes |
This lets business users modify the process without touching the workflow.
Show only the valid actions for the current state:
Show the item's complete journey:
| Timestamp | From | To | Action | By | Comment |
|---|---|---|---|---|---|
| Mar 15, 10:00 | — | Draft | Created | Jane | Initial draft |
| Mar 15, 14:30 | Draft | In Review | Submit | Jane | Ready for review |
| Mar 16, 09:15 | In Review | Draft | Reject | Bob | Needs budget section |
| Mar 16, 16:00 | Draft | In Review | Submit | Jane | Budget section added |
| Mar 17, 11:00 | In Review | Approved | Approve | Bob | Looks good |
Avoid "god states" — a state that can transition to any other state. This defeats the purpose of having a state machine. If you need a "reset" action, create it as a specific transition from specific states.
Split a workload into parallel branches, process them simultaneously, then aggregate the results. Dramatically reduces processing time for batch operations.