Skip to content
intermediatePhase 50 · LLD Practice

ATM Design

Design an ATM system with card authentication and cash dispensing.

1h 30m
0 problems
Topic Progress0%

Requirements

Functional Requirements

1. Card Operations:
   - Insert card
   - Eject card
   - Read card details

2. Authentication:
   - Enter PIN
   - Validate PIN with bank

3. Transactions:
   - Check balance
   - Withdraw cash
   - Deposit cash/check
   - Transfer between accounts

4. Cash Dispensing:
   - Dispense correct denominations
   - Handle insufficient funds
   - Track cash inventory

5. Receipt:
   - Print transaction receipt
   - Optional receipt for balance check

Non-Functional Requirements

1. Security: Encrypted PIN, secure communication
2. Reliability: Handle network failures gracefully
3. Availability: 24/7 operation
4. Atomicity: Complete transaction or rollback

ATM States

┌─────────────────────────────────────────────┐
│               ATM States                     │
├─────────────────────────────────────────────┤
│                                              │
│  Idle → CardInserted → PINVerified          │
│    │                         │               │
│    │                         ▼               │
│    │                    OperationSelected    │
│    │                         │               │
│    │            ┌────────────┼────────────┐  │
│    │            ▼            ▼            ▼  │
│    │         Balance     Withdraw      Deposit│
│    │            │            │            │  │
│    │            └────────────┼────────────┘  │
│    │                         ▼               │
│    │                    TransactionComplete  │
│    │                         │               │
│    │                         ▼               │
│    └──────────────────── CardEjected        │
│                                              │
└─────────────────────────────────────────────┘

State Pattern

ATM State Interface

public interface ATMState {
    void insertCard(ATM atm, Card card);
    void ejectCard(ATM atm);
    void enterPin(ATM atm, String pin);
    void selectOperation(ATM atm, OperationType type);
    void withdraw(ATM atm, int amount);
    void deposit(ATM atm, int amount);
    void checkBalance(ATM atm);
}

Idle State

public class IdleState implements ATMState {
    @Override
    public void insertCard(ATM atm, Card card) {
        atm.setCard(card);
        System.out.println("Card inserted. Please enter PIN.");
        atm.setState(new CardInsertedState());
    }
    
    @Override
    public void ejectCard(ATM atm) {
        System.out.println("No card to eject.");
    }
    
    @Override
    public void enterPin(ATM atm, String pin) {
        System.out.println("Insert card first.");
    }
    // Other methods throw IllegalStateException
}

CardInserted State

public class CardInsertedState implements ATMState {
    @Override
    public void enterPin(ATM atm, String pin) {
        if (atm.getCard().validatePin(pin)) {
            System.out.println("PIN verified. Select operation.");
            atm.setState(new AuthenticatedState());
        } else {
            System.out.println("Invalid PIN. Try again.");
            atm.incrementPinAttempts();
            if (atm.getPinAttempts() >= 3) {
                System.out.println("Card retained.");
                atm.ejectCard();
                atm.setState(new IdleState());
            }
        }
    }
    
    @Override
    public void ejectCard(ATM atm) {
        atm.setCard(null);
        System.out.println("Card ejected.");
        atm.setState(new IdleState());
    }
}

Authenticated State

public class AuthenticatedState implements ATMState {
    @Override
    public void selectOperation(ATM atm, OperationType type) {
        switch (type) {
            case CHECK_BALANCE:
                atm.setState(new BalanceInquiryState());
                break;
            case WITHDRAW:
                atm.setState(new WithdrawState());
                break;
            case DEPOSIT:
                atm.setState(new DepositState());
                break;
        }
    }
}

Withdraw State

public class WithdrawState implements ATMState {
    @Override
    public void withdraw(ATM atm, int amount) {
        // 1. Check balance
        if (atm.getCard().getBalance() < amount) {
            System.out.println("Insufficient funds.");
            return;
        }
        
        // 2. Check ATM cash
        if (!atm.getCashDispenser().hasEnoughCash(amount)) {
            System.out.println("ATM has insufficient cash.");
            return;
        }
        
        // 3. Dispense cash
        atm.getCashDispenser().dispense(amount);
        atm.getCard().deduct(amount);
        
        // 4. Print receipt
        atm.getReceiptPrinter().printWithdrawal(amount);
        
        // 5. Eject card
        atm.ejectCard();
        atm.setState(new IdleState());
    }
}

Transaction Flow

Complete Withdrawal Flow

┌──────┐     ┌────────┐     ┌──────────┐     ┌──────────┐
│ ATM  │     │ Bank   │     │ Cash     │     │ Receipt  │
│      │     │Server  │     │Dispenser │     │ Printer  │
└──┬───┘     └───┬────┘     └────┬─────┘     └────┬─────┘
   │             │               │                 │
   │ insertCard  │               │                 │
   │────────────▶│               │                 │
   │             │               │                 │
   │ enterPin    │               │                 │
   │────────────▶│               │                 │
   │  verify     │               │                 │
   │◀────────────│               │                 │
   │             │               │                 │
   │ selectWithdraw             │                 │
   │────────────▶│               │                 │
   │             │               │                 │
   │ enterAmount │               │                 │
   │────────────▶│               │                 │
   │  checkBalance               │                 │
   │◀────────────│               │                 │
   │             │               │                 │
   │             │               │ dispenseCash    │
   │             │               │◀────────────────│
   │             │               │  cash dispensed │
   │             │               │────────────────▶│
   │             │               │                 │
   │             │               │                 │ printReceipt
   │             │               │                 │◀────────────
   │             │               │                 │────────────▶
   │             │               │                 │
   │ ejectCard   │               │                 │
   │◀────────────│               │                 │

Transaction Recording

public class Transaction {
    private final String transactionId;
    private final TransactionType type;
    private final int amount;
    private final LocalDateTime timestamp;
    private final TransactionStatus status;
    
    public Transaction(TransactionType type, int amount) {
        this.transactionId = UUID.randomUUID().toString();
        this.type = type;
        this.amount = amount;
        this.timestamp = LocalDateTime.now();
        this.status = TransactionStatus.PENDING;
    }
}

Error Handling

public class TransactionErrorHandler {
    public void handle(TransactionError error) {
        switch (error.getType()) {
            case NETWORK_FAILURE:
                // Retry, then rollback
                retryOrRollback(error.getTransaction());
                break;
            case INSUFFICIENT_FUNDS:
                // Display message, return to menu
                displayMessage("Insufficient funds");
                break;
            case CASH_DISPENSER_ERROR:
                // Rollback, retain card
                rollbackTransaction(error.getTransaction());
                retainCard();
                break;
        }
    }
}

ATM Class

public class ATM {
    private ATMState state;
    private Card card;
    private final CashDispenser cashDispenser;
    private final ReceiptPrinter receiptPrinter;
    private final BankService bankService;
    
    public ATM() {
        this.state = new IdleState();
        this.cashDispenser = new CashDispenser();
        this.receiptPrinter = new ReceiptPrinter();
        this.bankService = new BankService();
    }
    
    public void setState(ATMState state) {
        this.state = state;
    }
    
    // Delegate all operations to current state
}

Follow-ups

Follow-up Questions

1. How to handle multi-currency?
   → Add Currency enum
   → Exchange rate service
   → Currency selection state

2. How to handle deposits?
   → Deposit state with check/cash scanning
   → Verification state for check clearing
   → Provisional credit

3. How to handle card retention?
   → RetainedCardState
   → Admin retrieval process
   → Notification to bank

4. How to handle ATM cash replenishment?
   → CashReplenishmentService
   → Threshold-based alerts
   → Scheduled replenishment

5. How to handle multi-account cards?
   → Account selection state
   → Different accounts (Savings, Checking)

Design Patterns Used

Pattern Usage
State ATM states (Idle, PIN, Auth, etc.)
Strategy Denomination selection
Observer Cash level monitoring
Factory Transaction creation
Singleton ATM instance

Security Considerations

1. PIN encryption (end-to-end)
2. Card data tokenization
3. Secure communication (TLS)
4. Transaction limits
5. Fraud detection
6. Card retention after failed attempts

Practice Problems

0/3solved
Design ATM Design System

Design a scalable ATM Design system. Cover high-level architecture, data model, and API design.

Solution
// Complete system design:
// - Functional + Non-functional requirements
// - Capacity estimation
// - Data model (SQL/NoSQL choice)
// - API endpoints
// - Component architecture
// - Scaling strategy
// - Monitoring & reliability
ATM Design Scaling

How would you scale ATM Design to handle 10x the current load? Identify bottlenecks and solutions.

Solution
// Scaling approach:
// 1. Load balancing
// 2. Database sharding/replication
// 3. Cache layer (Redis)
// 4. CDN for static assets
// 5. Async processing (queues)
// 6. Microservices decomposition
ATM Design Failure Modes

Analyze potential failure modes for ATM Design and design mitigation strategies.

Solution
// Failure mitigation:
// 1. Redundancy (multi-AZ)
// 2. Circuit breakers
// 3. Retry with backoff
// 4. Dead letter queues
// 5. Health checks
// 6. Graceful degradation

Quiz

1. What pattern is primarily used for ATM behavior?

Question 1 options

2. What happens after 3 failed PIN attempts?

Question 2 options

3. What must be checked before dispensing cash?

Question 3 options

4. What happens during a network failure?

Question 4 options

5. Why is the State pattern ideal for ATMs?

Question 5 options

Flashcards

Question

What pattern models ATM behavior?

Answer

State pattern. ATM has states: Idle, CardInserted, Authenticated, OperationSelected, etc. Behavior changes per state.

Question

ATM withdrawal flow?

Answer

1) Insert card, 2) Enter PIN, 3) Select withdrawal, 4) Enter amount, 5) Check balance+cash, 6) Dispense, 7) Print receipt, 8) Eject card.

Question

What happens after 3 failed PIN attempts?

Answer

Card is retained by ATM for security. ATM returns to Idle state. Bank is notified.

Question

What must be checked before dispensing cash?

Answer

Card balance must have sufficient funds AND ATM cash inventory must have enough cash in correct denominations.

Question

How to handle ATM network failures?

Answer

Retry logic, then rollback if retry fails. Transaction atomicity: complete or rollback completely.

Revision Notes

Key Takeaways

  • 1.ATM uses State pattern to model different states and allowed operations
  • 2.PIN verification has a 3-attempt limit before card retention
  • 3.Both card balance and ATM cash inventory must be checked before dispensing
  • 4.Transactions must be atomic: complete fully or rollback completely
  • 5.Error handling covers network failures, insufficient funds, and dispenser errors

Interview Tips

  • Show State pattern with clear state transitions
  • Explain the complete withdrawal flow with all checks
  • Discuss error handling and atomicity
  • Mention security considerations (PIN encryption, card retention)

Cheat Sheet

ATM Design - Cheat Sheet

States:
Idle → CardInserted → Authenticated → OperationSelected → Complete

Key Operations:

  • Insert/Eject card
  • PIN verification (3 attempts max)
  • Balance inquiry
  • Withdrawal (check balance + ATM cash)
  • Deposit
  • Transfer

Withdrawal Flow:

  1. Validate PIN
  2. Check card balance
  3. Check ATM cash
  4. Dispense cash
  5. Deduct from account
  6. Print receipt
  7. Eject card

Security:

  • PIN encryption
  • Card retention after failures
  • Transaction limits
  • Fraud detection

Patterns:
State (ATM states), Strategy (denomination), Observer (cash monitoring)