Overview
A state diagram (state machine) shows the states an object can be in and the events that move it between them, with optional guards (conditions) and actions. An order moves Created -> Paid -> Shipped -> Delivered, with Cancelled reachable only from Created or Paid.
Many LLD problems are state machines in disguise: vending machines, elevators, ATMs, traffic lights, ticket bookings, and order lifecycles. Drawing the diagram first makes the rules explicit, prevents illegal transitions, and leads directly to an implementation using a transition table or the State pattern.
It can be red, green, or yellow, and moves in a fixed cycle on a timer event. It can never jump from green directly to red without yellow; the diagram makes that rule impossible to miss.
When to use it
- Objects whose behavior depends on their current status.
- Rules about which actions are allowed when.
- Machines and workflows: vending, elevator, ATM, orders, tickets.
Where it shows up in interviews
Recognize it when: status fields with rules.
- Design an order system
- Design a ticket booking system
Recognize it when: device reacts to inputs differently by mode.
- Design a vending machine
- Design an elevator
- Design an ATM
Where it is used in real software
A popular JavaScript library for state machines and statecharts in UIs and workflows.
Implement workflow state machines in backend systems.
The TCP connection lifecycle (LISTEN, SYN_SENT, ESTABLISHED, TIME_WAIT) is a classic state machine.
Key terms
- State
- A condition the object can be in.
- Event / trigger
- Something that causes a transition.
- Guard
- Condition that must be true for the transition.
- Action
- Work done on the transition or on entry/exit.
- Terminal state
- No outgoing transitions (Delivered, Cancelled).
How it works, step by step
- 1List the states
Idle, HasMoney, Dispensing, OutOfStock.
- 2List the events
insertCoin, selectItem, dispense, refill.
- 3Draw allowed transitions
With guards and actions.
- 4Decide behavior for invalid events
Reject, ignore, or refund.
- 5Implement
Transition table for simple cases, State pattern for rich behavior.
STEP 1Idle: waiting. insertCoin moves to HasMoney. selectItem here is rejected.
Order lifecycle transition table
Allowed transitions
| From | Event | Guard | To |
|---|---|---|---|
| Created | pay | amount matches | Paid |
| Created | cancel | - | Cancelled |
| Paid | ship | stock reserved | Shipped |
| Paid | cancel | - | Cancelled (refund) |
| Shipped | deliver | - | Delivered |
| Shipped | cancel | - | Not allowed |
NOWFrom: Created | Event: pay | Guard: amount matches | To: Paid
Any event not in the table is illegal, so 'cancel after ship' becomes an explicit error instead of a silent bug.
Implementation
type OrderState = "created" | "paid" | "shipped" | "delivered" | "cancelled";type OrderEvent = "pay" | "ship" | "deliver" | "cancel"; const transitions: Record<OrderState, Partial<Record<OrderEvent, OrderState>>> = { created: { pay: "paid", cancel: "cancelled" }, paid: { ship: "shipped", cancel: "cancelled" }, shipped: { deliver: "delivered" }, delivered: {}, cancelled: {},}; class Order { state: OrderState = "created"; readonly history: OrderState[] = ["created"]; apply(event: OrderEvent) { const next = transitions[this.state][event]; if (!next) throw new Error(`Cannot ${event} when ${this.state}`); this.state = next; this.history.push(next); }} const o = new Order();o.apply("pay");o.apply("ship");// o.apply("cancel") -> Error: Cannot cancel when shippedComplexity and performance
Table or switch.
Every cell is allowed or rejected.
Trade-offs
Tables are compact for simple transitions; the State pattern suits states with rich, different behavior.
Explicit machines add upfront modeling but eliminate a class of bugs from scattered status checks.
Variants and related techniques
Nested states (Operating > Moving/Idle) reduce duplication.
State derived by replaying transition events.
Common mistakes
- Status checks scattered through services.
Fix: Centralize transitions in the entity or a state machine.
- Forgetting invalid events.
Fix: Decide and test behavior for every state-event pair.
Interview questions
How would you model a vending machine?
As a state machine with states Idle, HasMoney, Dispensing, and OutOfStock, events insertCoin, selectItem, cancel, and refill, guarded by credit and stock, implemented with the State pattern so each state handles events differently.
How do you prevent illegal transitions?
Define allowed transitions in one place (table or State classes), route every change through it, and throw or ignore when an event is not allowed in the current state.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Draw a state diagram for a traffic light with pedestrian button | Easy | Events and timers. |
| Draw a state diagram for an elevator car | Medium | Doors and movement. |