Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

ATM System

Design an Automated Teller Machine (ATM) system with state management, authentication, concurrent transactions, and cash dispensing.

Design an ATM (Automated Teller Machine) system that allows users to perform basic banking transactions such as checking balance, withdrawing cash, and depositing cash. The system should handle user authentication, communicate with the bank’s main system, and support concurrent transactions while maintaining data consistency.

In this problem, you’ll design a system that coordinates between a local terminal and a remote bank server, handling hardware constraints like cash denominations and software challenges like race conditions in account balances.


Design a secure Automated Teller Machine that authenticates users, processes various banking transactions, and dispenses physical cash based on inventory.

Functional Requirements:

  • Transactions: Support basic actions: checking account balance, withdrawing cash, and depositing cash.
  • Authentication: Verify users via ATM card insertion and 4-6 digit PIN entry.
  • Bank Communication: Securely communicate with the bank’s main system to verify accounts and process transactions.
  • Cash Dispenser: Dispense requested amounts using multiple note denominations.
  • Concurrency: Ensure correct behavior when multiple users or transactions happen simultaneously for the same account.
  • Validation: Check for sufficient funds before processing any withdrawal request.
  • Denomination Logic: Handle cases where the exact amount cannot be dispensed due to available note mix.

Non-Functional Requirements:

  • Object-Oriented Design: Clear separation of concerns with well-defined roles for each class.
  • Modularity: Easy to add future enhancements like new transaction types or authentication methods.
  • Thread Safety: Balance updates and transaction processing must be safe from race conditions.
  • State Management: Maintain a clear state flow from idle to card insertion, authentication, and completion.
  • Reliability: Core transaction logic should be robust, testable, and maintainable over time.

The ATM acts as a client that interacts with a secure BankServer API.

Diagram
classDiagram
    class ATM {
        -ATMState currentState
        -CashDispenser dispenser
        -BankService bankLink
        +insertCard(card)
        +authenticate(pin)
        +performTransaction(txn)
    }
    
    class ATMState {
        <<interface>>
        +handleAction()
    }
    
    class CashDispenser {
        -Map~Note, Qty~ inventory
        +dispense(amount)
    }

    class Account {
        -long balance
        +debit(amount)
        +credit(amount)
    }

    ATM --> ATMState
    ATM --> CashDispenser
    Account "1" -- "many" Transaction

Diagram

If a user wants $180, the machine should ideally give 1x$100, 1x$50, 1x$20, and 1x$10.

Solution: Use the Chain of Responsibility Pattern. Create handlers for each denomination (HundredHandler, FiftyHandler, etc.). Each handler calculates how many notes of its type it can provide and passes the remainder to the next handler in the chain.

What if the bank debits the account but the ATM hardware jams and fails to dispense cash?

Solution: Use a Two-Phase Commit logic. The bank “holds” the funds, the ATM dispenses the cash, and only after the hardware confirms successful dispensing does the ATM send a “commit” message to the bank to finalize the debit.

A user might try to withdraw their entire balance from two different ATMs at the exact same time.

Solution: Implement Pessimistic Locking on the account record at the database level. When one ATM initiates a transaction, the server locks that account until the transaction is complete, forcing the second ATM to wait.


By solving this problem, you’ll master:

  • State Pattern - Managing complex, multi-step lifecycles.
  • Chain of Responsibility - Implementing greedy algorithms for resource allocation.
  • Concurrency Control - Using locking mechanisms to prevent data corruption.
  • Secure System Design - Coordinating client-server interactions in a high-stakes environment.

Ready to see the full implementation? Open the interactive playground to access:

  • 🎯 Step-by-step guidance through the 8-step LLD approach
  • 📊 Interactive UML builder to visualize your design
  • 💻 Complete Code Solutions in Python, Java, C++, TypeScript, JavaScript, C#
  • 🤖 AI-powered review of your design and code

After mastering the ATM System, try these similar problems: