ATM Machine Design
ATM LLD models card authentication, PIN validation, cash dispensing, balance inquiry, and transaction logging — often coordinated with a remote BankHost abstraction.
Introduction
ATM LLD models card authentication, PIN validation, cash dispensing, balance inquiry, and transaction logging — often coordinated with a remote BankHost abstraction.
Split hardware interfaces (CardReader, CashDispenser, Printer) from AtmService orchestration. State diagram for session: idle → authenticated → transaction → idle.
Discuss rollback when dispense fails after debit.
Understanding the topic
Key concepts
- Components: ATM, CardReader, CashDispenser, Keypad, Screen, BankHost.
- Session after successful PIN.
- Operations: withdraw, deposit, balance, transfer.
- Transaction log for audit.
- Hardware failure compensation (rollback credit).
- Daily withdrawal limits on account.
classDiagramclass ATM {+withdraw(amount)+deposit(amount)}class CashDispenserclass CardReaderATM --> CashDispenserATM --> CardReader
Step-by-step explanation
- Insert card; CardReader reads token.
- Validate PIN with BankHost.
- User selects operation and amount.
- AtmService debits/credits via BankHost.
- CashDispenser dispenses on withdraw.
- Print receipt; eject card; end session.
Informative example
ATM with hardware abstractions and compensating transaction on dispense failure:
public interface BankHost {Optional<Account> authenticate(String cardToken, String pin);boolean debit(Account account, Money amount);void credit(Account account, Money amount);}public interface CashDispenser {boolean dispense(Money amount);}public final class AtmService {private final BankHost bank;private final CashDispenser dispenser;private final List<Transaction> log = new ArrayList<>();public AtmService(BankHost bank, CashDispenser dispenser) {this.bank = bank;this.dispenser = dispenser;}public Result withdraw(Account account, Money amount) {if (amount.isZero()) return Result.failed("invalid amount");if (!bank.debit(account, amount)) return Result.failed("insufficient funds");if (!dispenser.dispense(amount)) {bank.credit(account, amount);return Result.failed("dispenser jam");}log.add(Transaction.withdraw(account.id(), amount));return Result.ok();}}public record Account(String id, Money balance) {}public record Transaction(String accountId, Money amount, Instant at) {static Transaction withdraw(String accountId, Money amount) {return new Transaction(accountId, amount, Instant.now());}}
AtmController handles UI flow; AtmService owns transactional integrity.
Real-world use
Real-world applications
- Hardware abstraction LLD question.
- Compensating transaction pattern practice.
- State machine for session lifecycle.
Best practices
- DIP for all hardware and bank connections.
- Rollback on partial failure.
- Never store PIN — validate remotely or hash.
- Idempotent transaction ids for retry.
- Separate read-only balance from withdraw path.
Common mistakes
- Monolithic ATM class with pin + cash + sql.
- No rollback when dispense fails.
- Storing plaintext PIN on card model.
- Skipping transaction audit log.
Advanced interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1BeginnerQuestionMain ATM classes?+
Answer
2BeginnerQuestionDispense fails after debit?+
Answer
3IntermediateQuestionHow model deposit?+
Answer
4IntermediateQuestionConcurrent access same account?+
Answer
5AdvancedQuestionDesign ATM chain with shared cash replenishment.+
Answer
Summary
ATM splits UI, service, hardware, bank host. Compensating credit on dispense failure. Session state machine for authenticated flows. Transaction log for audit trail. DIP enables testing without real hardware.