How do you design the order state machine in the shopping system?
Fast recall
Quick revision
Core answer
Understanding of finite state machines for modeling object lifecycles, knowledge of the State design pattern to avoid if-else chains, and awareness that business operations have preconditions based on current state
Using a simple status enum with giant if-else blocks in Order methods checking current status before every operation, allowing invalid transitions like cancelling a delivered order, or not maintaining an audit trail of state changes
Mention state transition validation, audit logging of state changes with timestamps and reasons, handling edge cases like partial shipments or returns, and how certain operations like refund are only valid in specific states
Interview-ready guide
Interview answer
An order has a clear lifecycle — placed, processing, shipped, delivered — with side branches to cancelled and returned. The important thing isn't the list of states, it's the rules between them: a placed order can be cancelled, but once it's shipped you can't just cancel it, you'd have to go through a return. So I'd model it with the State pattern.
I'd define an OrderState interface with the transition methods — ship, cancel, deliver — and then a concrete class for each state. PlacedState allows ship and cancel but throws on deliver, because you can't deliver something that hasn't shipped. ShippedState allows deliver but throws on cancel. The Order object holds its current state and delegates: Order.cancel just calls state.cancel and replaces the state with whatever comes back. The beautiful part is that an invalid transition, like jumping from delivered back to placed, simply can't be expressed — there's no method path that does it.
The naive alternative is a single status enum where every method re-checks the current status with if-statements. That works until someone adds a new operation and forgets one of the checks, and suddenly an order can take an illegal jump that corrupts your data. Centralising the rules inside the state classes removes that whole category of bug. I'd make sure to include the cancelled and returned branches too, because the happy path isn't the whole story — handling cancellation and returns cleanly is exactly what an interviewer is probing for.
How do you design the order state machine in the shopping system
Direct Answer
Model Order as a state machine with states like PLACED, PAYMENT_PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED, and RETURNED. Each state defines valid transitions—for example, PLACED can move to PROCESSING or CANCELLED, but SHIPPED cannot be directly cancelled. Implement using the State design pattern: create an OrderState interface with methods like cancel, ship, and deliver, then concrete classes PlacedState, ShippedState each encapsulating allowed operations. The Order object holds a reference to its current state and delegates operations to it, ensuring invalid transitions are rejected at compile time through type safety.
Deep Dive & Architecture
Define legal transitions explicitly
A simple path is PLACED → PAID → PACKED → SHIPPED → DELIVERED. PLACED or PAID may move to CANCELLED under the business rules; DELIVERED may open a separate return workflow rather than jumping backwards. A transition table should state the allowed source, target, actor, and guard.
Change state and record history together
Order.transitionTo(next, actor, reason) validates the move, changes the status, and appends an OrderStatusHistory entry in one transaction. For example, only a successful payment event with the matching order and amount may move PLACED to PAID. Repeating the same event should leave the order unchanged rather than charging or reserving again.
Side effects follow a committed transition
After PAID commits, fulfilment can be notified; after CANCELLED, reserved stock can be released and a refund requested when needed. An outbox or reliable event mechanism prevents a database commit from being lost before the message is sent. The state machine owns legality, while payment, inventory, and notification services own their work.
Common Mistakes & Pitfalls
- A bare status field with no transition rules — lets an order jump from delivered back to placed.
- Duplicated transition checks in every method — the State pattern centralizes them per state.
- No CANCELLED/RETURNED branches — the happy path isn't the whole lifecycle.
- Mutating status outside the state object — all transitions should go through the state.
Check your understanding
Answer these without looking back at the article.
- How do you design the product review and rating system?
- Design an online shopping system like Amazon. What are the core classes?
- How do you design the inventory management component?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.