Skip to content

State Machines — Detailed#

Anatomy#

stateDiagram-v2
  [*] --> Idle
  Idle --> Selecting : insert_coin
  Selecting --> Dispensing : choose_item / guard balance >= price
  Selecting --> Idle : cancel / refund
  Dispensing --> Idle : delivered
  Dispensing --> OutOfStock : stock == 0
  OutOfStock --> Idle : reset
  • StatesIdle, Selecting, ...
  • Eventsinsert_coin, choose_item, ...
  • Transitions — state × event → new state.
  • Guards — predicates that must hold for the transition (balance >= price).
  • Actions / side-effects — emit refund, call payment, etc.
  • Initial / final states.

Hierarchical state machines (HSM)#

stateDiagram-v2
  state Connected {
    [*] --> Idle
    Idle --> Streaming : play
    Streaming --> Paused : pause
    Paused --> Streaming : play
  }
  [*] --> Disconnected
  Disconnected --> Connected : connect
  Connected --> Disconnected : disconnect

Composite state Connected shares "on disconnect → outer" without repeating transitions in every sub-state.

Two implementation styles#

A. Switch + enum (small / inline)#

enum OrderState { CREATED, PAID, SHIPPED, DELIVERED, CANCELLED }

OrderState next(OrderState s, Event e) {
  return switch (s) {
    case CREATED -> switch (e) {
      case PAY    -> PAID;
      case CANCEL -> CANCELLED;
      default     -> throw new IllegalTransition(s, e);
    };
    case PAID -> switch (e) {
      case SHIP   -> SHIPPED;
      case REFUND -> CANCELLED;
      default     -> throw new IllegalTransition(s, e);
    };
    // ...
  };
}

Pros: simple, fast. Cons: scattered guards/actions.

B. State pattern (large / per-state behaviour)#

classDiagram
  class Order {
    -state: OrderState
    +on(event)
  }
  class OrderState {
    <<interface>>
    +on(order, event)
  }
  class Created
  class Paid
  class Shipped
  class Delivered
  OrderState <|.. Created
  OrderState <|.. Paid
  OrderState <|.. Shipped
  OrderState <|.. Delivered
  Order o--> OrderState

Each state class encapsulates its allowed transitions + behaviour. Best when each state has substantial logic (Vending Machine, Elevator, Game).

Validation rules#

For correctness, model and check: - Total: every (state, event) pair is handled (or explicitly rejected). - Reachable: no orphan states. - No deadlocks: every state has at least one outgoing transition (except final). - Determinism: at most one transition per (state, event, guard).

Tools: TLA+, PlantUML state-machine validators, xstate visualisers.

Persistence#

  • Persist (entity_id, state, version).
  • Compare-and-swap on version when transitioning → optimistic concurrency.
  • Or store events: state = fold(events) — see event sourcing.

When the model breaks#

  • States proliferate (10+ states with criss-cross transitions) — refactor into HSM or split into multiple machines.
  • Guards become complex business rules — extract a separate domain service.
  • Transitions need long-running side-effects — model as a saga or workflow (Temporal, Cadence).

Where this shows up#

  • Vending Machine, ATM, Elevator, Hotel, Movie booking (Tier 11 LLD problems).
  • Order systems (e-commerce, food delivery, Uber trips).
  • Payment lifecycle (auth → capture → settle → refund).
  • Connection lifecycle (WS / SSE / gRPC streams).
  • Game character states (idle / running / jumping / dead).

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
HLD Distributed transactions 2PC, TCC, sagas, outbox/inbox distributed-transactions
HLD Observability metrics, logs, traces, SLOs observability
HLD Realtime protocols WS / SSE / polling / gRPC streaming realtime-protocols
HLD Event sourcing + CQRS commands -> events; separate read model event-sourcing-cqrs
LLD State machines FSM, HSM, transitions, guards state-machines
LLD OOP pillars encapsulation, abstraction, inheritance, polymorphism oop-pillars
LLD Structural patterns Adapter, Decorator, Facade, Proxy, Composite structural-patterns
LLD Behavioural patterns Strategy, Observer, State, Command, Chain behavioral-patterns
LLD Concurrency primitives mutex, semaphore, RW lock, atomic, CAS concurrency-primitives