How to Design a Vending Machine System?
Learn how to design a vending machine as a finite state machine with safe inventory tracking, payment isolation, and fault recovery.
Expected Interview Answer
A vending machine system is best modeled as a finite state machine with a small set of explicit states (idle, selecting, awaiting payment, dispensing, returning change, out of stock) and clear transitions, keeping inventory and payment as separate concerns coordinated by the state machine.
The design starts with enumerating states and legal transitions: the machine sits idle, moves to “item selected” when a button is pressed, moves to “awaiting payment” and accumulates inserted coins or a card charge, then either transitions to “dispensing” once payment meets or exceeds price (with change calculated and returned) or back to idle if the transaction is cancelled. Inventory is tracked per slot with a quantity and price, decremented only after a successful dispense confirmed by a sensor (not merely after payment, to avoid losing inventory count on a jam), and a slot with zero quantity transitions the machine to reject further selections of that item. Payment handling is isolated behind an interface so cash, card, and mobile-wallet payment methods can be swapped without touching the state machine, and a hardware fault (jam, sensor failure) has its own recovery state that halts dispensing and triggers a refund rather than silently losing money. This separation of concerns — state machine, inventory, payment, hardware I/O — keeps the design testable and extensible to networked/remote-monitored machines.
- A finite state machine makes every legal transition explicit and easy to reason about
- Decrementing inventory only after confirmed dispense avoids losing count on jams
- Isolating payment behind an interface lets cash/card/wallet be swapped independently
- A dedicated fault/recovery state prevents silently losing a customer’s money on hardware failure
AI Mentor Explanation
A vending machine system is like the strict sequence of states an umpire enforces during an over: waiting for the bowler to be ready, then the delivery, then either a legal ball recorded or a no-ball requiring a re-do, never skipping a state out of order. The scoreboard (inventory) only updates once the umpire actually confirms what happened on the field, not the moment the bowler simply intends to bowl. If something goes wrong mid-delivery, there is a defined recovery state (dead ball) rather than the game silently breaking. That explicit, ordered state progression is exactly how a vending machine’s state machine is structured.
Step-by-Step Explanation
Step 1
Define states and transitions
Enumerate idle, item selected, awaiting payment, dispensing, returning change, out of stock, and fault/recovery as explicit states with legal transitions.
Step 2
Isolate payment behind an interface
Cash, card, and mobile-wallet handling implement a common interface so the state machine does not know payment method details.
Step 3
Decrement inventory only on confirmed dispense
A sensor confirms the item physically dropped before the slot’s quantity is decremented, avoiding phantom losses on a jam.
Step 4
Handle faults explicitly
Jams or sensor failures transition to a dedicated fault state that halts the machine and triggers a refund instead of losing the transaction silently.
What Interviewer Expects
- Models the machine as an explicit finite state machine with named states and legal transitions
- Separates payment handling behind an interface from the core state machine
- Decrements inventory only after a confirmed (sensor-verified) dispense, not on payment alone
- Handles hardware faults with a dedicated recovery/refund state rather than ignoring them
Common Mistakes
- Hardcoding payment logic directly into the state machine instead of behind an interface
- Decrementing inventory as soon as payment is accepted, losing count accuracy on a jam
- Not modeling an explicit fault/recovery state for hardware failures
- Allowing invalid transitions (e.g., dispensing without payment confirmed) due to loose state checks
Best Answer (HR Friendly)
“A vending machine is really a state machine: it is idle, then someone selects an item, then it waits for enough payment, then it either dispenses the item and gives change or cancels back to idle. The important design detail is that inventory only gets reduced once a sensor confirms the item actually came out, so a jam does not silently lose track of stock, and any hardware failure has its own clear recovery path that refunds the customer instead of just failing silently.”
Code Example
const STATES = {
IDLE: "idle",
SELECTED: "selected",
AWAITING_PAYMENT: "awaiting_payment",
DISPENSING: "dispensing",
FAULT: "fault",
}
class VendingMachine {
constructor(inventory) {
this.state = STATES.IDLE
this.inventory = inventory // { slotId: { price, quantity } }
this.balance = 0
this.selectedSlot = null
}
selectItem(slotId) {
if (this.state !== STATES.IDLE) throw new Error("Invalid transition")
const slot = this.inventory[slotId]
if (!slot || slot.quantity <= 0) throw new Error("Out of stock")
this.selectedSlot = slotId
this.state = STATES.AWAITING_PAYMENT
}
insertPayment(amount) {
if (this.state !== STATES.AWAITING_PAYMENT) throw new Error("Invalid transition")
this.balance += amount
const slot = this.inventory[this.selectedSlot]
if (this.balance >= slot.price) this.state = STATES.DISPENSING
}
onDispenseSensorConfirmed() {
if (this.state !== STATES.DISPENSING) throw new Error("Invalid transition")
const slot = this.inventory[this.selectedSlot]
slot.quantity -= 1 // only decrement after physical confirmation
const change = this.balance - slot.price
this.balance = 0
this.selectedSlot = null
this.state = STATES.IDLE
return { change }
}
onJamDetected() {
this.state = STATES.FAULT // triggers refund workflow externally
}
}Follow-up Questions
- How would you extend this design to support networked, remotely-monitored vending machines?
- What happens to a customer’s money if the machine jams after payment but before dispensing?
- How would you support multiple payment methods (cash, card, mobile wallet) cleanly?
- How would you model a slot going out of stock mid-transaction?
MCQ Practice
1. Why is a finite state machine a good fit for modeling a vending machine?
An explicit state machine defines exactly which transitions are legal, preventing invalid states like dispensing before payment is confirmed.
2. Why should inventory be decremented only after a confirmed dispense sensor event, not right after payment?
If inventory decremented on payment alone, a jam after payment would leave inventory undercounted even though the item never left the slot.
3. Why isolate payment handling (cash/card/wallet) behind a common interface?
Isolating payment behind an interface decouples the state machine from payment-method specifics, so new methods plug in without touching core logic.
Flash Cards
How should a vending machine be modeled? — As a finite state machine with explicit states (idle, selecting, awaiting payment, dispensing, fault) and legal transitions.
When should inventory be decremented? — Only after a sensor confirms the item was physically dispensed, not right after payment.
Why isolate payment behind an interface? — So cash, card, and wallet payment methods can be added or swapped without changing the state machine.
How should hardware jams be handled? — With a dedicated fault/recovery state that halts dispensing and triggers a refund rather than failing silently.