Chapter 11 · Article 50 of 55

Designing an ATM Machine System

Design an Automated Teller Machine (ATM) system that enables bank customers to perform self-service banking operations without visiting a branch. The system must handle cash wit…

Article outline15 sections on this page

Problem Statement

Design an Automated Teller Machine (ATM) system that enables bank customers to perform self-service banking operations without visiting a branch. The system must handle cash withdrawal with denomination selection, cash deposits, balance inquiries, fund transfers between accounts, mini statement generation, PIN changes, and receipt printing.

The ATM operates as a physical kiosk connected to a bank's central network. A customer inserts their debit/credit card, authenticates via PIN, selects a transaction type, and the system processes the request by communicating with the bank's backend. The design must account for hardware components (card reader, cash dispenser, receipt printer, keypad, screen), network communication, security protocols, and failure scenarios unique to physical banking devices.

Consider a bank deploying 5,000+ ATMs across a country, each handling 200-500 transactions daily, with peak loads during salary days and holidays. The system must guarantee transaction integrity even during network partitions, hardware failures, or power outages.


Requirements

Functional Requirements

  1. Card Authentication (PIN) - Read card data via magnetic stripe or chip, validate PIN against the bank's authentication service with a maximum of 3 attempts before card retention.
  2. Balance Inquiry - Display current available balance and total balance (including holds) from the linked account.
  3. Cash Withdrawal - Allow customers to select an amount, choose denomination preferences, validate against daily limits and available balance, and dispense cash.
  4. Cash Deposit - Accept cash or cheque deposits, count and validate notes, and credit the account (immediate for cash, pending for cheques).
  5. Fund Transfer - Transfer funds between accounts within the same bank or via interbank networks (NEFT/IMPS/RTGS).
  6. Mini Statement - Display or print the last 5-10 transactions with date, type, and amount.
  7. PIN Change - Allow authenticated users to change their ATM PIN after verifying the current PIN.
  8. Receipt Printing - Generate a printed receipt with transaction details, timestamp, ATM ID, and masked account number.

Non-Functional Requirements

  1. Security - End-to-end encryption (TLS 1.3) for all bank communication, PIN encryption using HSM (Hardware Security Module), session timeout after 30 seconds of inactivity, PCI-DSS compliance.
  2. Availability - 99.9% uptime target; graceful degradation when network is unavailable.
  3. Transaction Atomicity - All-or-nothing guarantee; no partial withdrawals debited without cash dispensed.
  4. Audit Trail - Every action logged with timestamp, ATM ID, card number (masked), transaction type, and outcome.
  5. Concurrent Access Handling - Prevent double-spending when the same account is accessed simultaneously from multiple ATMs.
  6. Performance - Transaction completion within 15 seconds; PIN validation within 3 seconds.
  7. Reliability - Automatic recovery from hardware faults; transaction journal for reconciliation.

Constraints & Assumptions

  • Limited Cash Denominations - ATM holds only 4-5 denomination types (e.g., ₹100, ₹200, ₹500, ₹2000). Not all amounts are dispensable.
  • Daily Withdrawal Limits - Per-card limit (e.g., ₹25,000/day) enforced across all ATMs, not per-ATM.
  • Network Connectivity - Primary leased line + backup cellular connection to bank servers. Latency typically 50-200ms.
  • Physical Hardware Constraints - Card reader may jam, cash dispenser has finite cassettes (4 cassettes × 2,500 notes each), receipt printer has limited paper roll.
  • Single User at a Time - Physical constraint means no concurrent sessions on the same ATM.
  • Power Supply - UPS backup for 15-30 minutes to complete in-progress transactions during power failure.
  • Cash Replenishment - Scheduled 1-2 times daily by armored vehicles; ATM must track remaining notes per denomination.

Key Entities & Relationships

EntityResponsibility
ATMOrchestrates hardware components and manages session lifecycle
AccountHolds balance, transaction history, daily limits
CardLinks to account(s), stores card number, expiry, PIN hash
TransactionAbstract base for all operation types
WithdrawalExtends Transaction; includes amount, denominations dispensed
DepositExtends Transaction; includes deposited amount, note count
TransferExtends Transaction; includes source/destination accounts
BalanceInquiryExtends Transaction; read-only operation
CashDispenserManages cassettes, tracks note counts, dispenses cash
CardReaderReads/ejects/retains cards
ScreenDisplays UI prompts and information
KeypadCaptures PIN and numeric input (encrypted at hardware level)
ReceiptPrinterPrints transaction receipts
BankNetworkInterface to bank's core banking system
SessionTracks authenticated user, timeout, transaction count
TransactionLogImmutable audit log of all operations

Relationships:

  • ATM has CardReader, CashDispenser, Screen, Keypad, ReceiptPrinter (composition)
  • ATM connects to BankNetwork (association)
  • Session belongs to ATM, references Card and Account
  • Transaction belongs to Session, logged in TransactionLog
  • Card links to one or more Accounts
  • CashDispenser contains multiple Cassettes (each with denomination and count)

ASCII Class Diagram

┌─────────────────────────────────────────────────────────────────┐
│                            ATM                                   │
├─────────────────────────────────────────────────────────────────┤
│ - atmId: String                                                  │
│ - location: String                                               │
│ - state: ATMState                                                │
│ - currentSession: Session                                        │
├─────────────────────────────────────────────────────────────────┤
│ + insertCard(): void                                             │
│ + authenticateUser(pin): boolean                                 │
│ + selectTransaction(type): Transaction                           │
│ + endSession(): void                                             │
└──────────┬──────────┬──────────┬──────────┬──────────┬──────────┘
           │          │          │          │          │
    ┌──────▼──┐ ┌─────▼────┐ ┌──▼───┐ ┌───▼──┐ ┌────▼─────────┐
    │CardReader│ │CashDispen│ │Screen│ │Keypad│ │ReceiptPrinter│
    ├─────────┤ │ser       │ ├──────┤ ├──────┤ ├──────────────┤
    │+read()  │ ├──────────┤ │+show()│ │+get  │ │+print()      │
    │+eject() │ │-cassettes│ │+clear()││Input()│ │+hasPaper()   │
    │+retain()│ │+dispense()│ └──────┘ └──────┘ └──────────────┘
    └─────────┘ │+getCount()│
                └──────────┘

┌───────────────────────────────────────────────────┐
│              Transaction (Abstract)                │
├───────────────────────────────────────────────────┤
│ - transactionId: String                           │
│ - timestamp: DateTime                             │
│ - amount: Decimal                                 │
│ - status: TransactionStatus                       │
│ - accountId: String                               │
├───────────────────────────────────────────────────┤
│ + execute(): TransactionResult                    │
│ + rollback(): void                                │
└───────┬───────────┬───────────┬───────────────────┘
        │           │           │
┌───────▼───┐ ┌─────▼─────┐ ┌──▼──────────┐ ┌──────────────┐
│Withdrawal │ │  Deposit   │ │  Transfer   │ │BalanceInquiry│
├───────────┤ ├───────────┤ ├─────────────┤ ├──────────────┤
│-denomMap  │ │-noteCount │ │-destAccount │ │              │
│+execute() │ │+execute() │ │+execute()   │ │+execute()    │
└───────────┘ └───────────┘ └─────────────┘ └──────────────┘

┌──────────────────────┐       ┌──────────────────────┐
│       Session        │       │    BankNetwork       │
├──────────────────────┤       ├──────────────────────┤
│ - sessionId: String  │       │ + validatePIN()      │
│ - card: Card         │       │ + getBalance()       │
│ - startTime: DateTime│       │ + debit()            │
│ - lastActivity: Time │       │ + credit()           │
│ - txnCount: int      │       │ + transfer()         │
├──────────────────────┤       │ + getStatement()     │
│ + isExpired(): bool  │       └──────────────────────┘
│ + refresh(): void    │
└──────────────────────┘

State Machine Design

                         ┌─────────────────────────────────────┐
                         │          TIMEOUT (any state)         │
                         │     ──► SESSION_EXPIRED ──► IDLE    │
                         └─────────────────────────────────────┘

    ┌──────┐   card inserted    ┌────────────────┐
    │      │ ─────────────────► │                │
    │ IDLE │                    │ AUTHENTICATING │
    │      │ ◄───────────────── │                │
    └──┬───┘   card ejected     └───┬────────┬───┘
       ▲                            │        │
       │                    PIN     │        │ PIN wrong
       │                  correct   │        │ 3 times
       │                            ▼        ▼
       │                 ┌──────────────┐  ┌───────────────┐
       │                 │  SELECTING   │  │ CARD_RETAINED │
       │                 │ _TRANSACTION │  └───────┬───────┘
       │                 └──────┬───────┘          │
       │                        │                  │
       │              transaction selected         │
       │                        │                  │
       │                        ▼                  │
       │                 ┌─────────────┐           │
       │                 │ PROCESSING  │           │
       │                 └───┬─────┬───┘           │
       │                     │     │               │
       │            success  │     │ failure       │
       │                     ▼     ▼               │
       │    ┌────────────────┐   ┌───────┐        │
       │    │  DISPENSING /  │   │ ERROR │        │
       │    │   PRINTING    │   └───┬───┘        │
       │    └───────┬────────┘       │            │
       │            │                │            │
       │            ▼                ▼            │
       │    ┌──────────────┐  (back to select)   │
       │    │ COMPLETING   │─────────────────┐   │
       │    └──────┬───────┘                 │   │
       │           │                         ▼   │
       │           │ another txn?    SELECTING   │
       │           │ ──────────────► _TRANSACTION│
       │           │                             │
       │           │ done / eject card           │
       └───────────┴─────────────────────────────┘

State Transitions:

FromEventTo
IDLECard insertedAUTHENTICATING
AUTHENTICATINGPIN correctSELECTING_TRANSACTION
AUTHENTICATINGPIN wrong (attempt < 3)AUTHENTICATING
AUTHENTICATINGPIN wrong (attempt = 3)CARD_RETAINED
CARD_RETAINEDCard retained, notify bankIDLE
SELECTING_TRANSACTIONTransaction type selectedPROCESSING
PROCESSINGTransaction successfulDISPENSING/PRINTING
PROCESSINGTransaction failedERROR
ERRORUser acknowledgesSELECTING_TRANSACTION
DISPENSING/PRINTINGCash/receipt deliveredCOMPLETING
COMPLETINGAnother transactionSELECTING_TRANSACTION
COMPLETINGEject cardIDLE
Any state30s inactivity timeoutSESSION_EXPIRED → IDLE

Design Decisions & Trade-offs

1. Cash Dispensing Algorithm

Option A: Minimize Number of Notes - Use greedy algorithm with largest denominations first. Reduces wear on dispenser, faster dispensing.

Option B: Balanced Distribution - Spread across denominations to avoid depleting large-note cassettes quickly.

Decision: Use a configurable strategy. Default to "minimize notes" but switch to "balanced" when any cassette drops below 20% capacity. This extends time between replenishments.

2. Transaction Rollback Strategy

Use a two-phase commit approach with the bank:

  1. Phase 1 (Reserve): Bank places a hold on the amount, returns authorization code.
  2. Phase 2 (Confirm/Cancel): After cash is dispensed, send confirmation. If dispensing fails, send cancellation to release the hold.

Trade-off: Adds latency (two network round-trips) but guarantees atomicity. Holds expire after 5 minutes if no confirmation received, protecting against ATM crashes.

3. Session Management

  • Timeout: 30 seconds of inactivity triggers card ejection. If card not taken within 15 seconds, retain it.
  • Max Transactions: Limit to 5 transactions per session to prevent hogging during peak hours.
  • Session Token: Generated server-side, invalidated on timeout or explicit logout.

4. Offline Mode

When network connectivity is lost:

  • Allowed: Balance inquiry (last cached), PIN change (queued).
  • Blocked: Withdrawals above ₹2,000 (configurable floor limit), transfers, deposits.
  • Floor Limit Withdrawals: Small withdrawals authorized locally using stored card data and risk scoring. Reconciled when connectivity resumes.

Trade-off: Increases fraud risk but maintains basic service availability.

5. Denomination Tracking and Low-Cash Alerts

  • Each cassette maintains a real-time note count (decremented on dispense, verified during replenishment).
  • Alert Thresholds: Warning at 25% remaining, critical at 10%, out-of-service when any required denomination is empty.
  • Alerts sent to bank operations center via SNMP/push notification for proactive replenishment scheduling.

Design Patterns Used

PatternApplication
StateATM lifecycle (Idle, Authenticating, Processing, etc.). Each state encapsulates valid transitions and behaviors.
StrategyCash dispensing algorithms are interchangeable strategies. The ATM selects based on cassette levels.
CommandEach transaction type (Withdrawal, Deposit, Transfer) is a command object with execute() and rollback() methods. Enables undo and logging.
Chain of ResponsibilityValidation pipeline: CardValidator → PINValidator → BalanceValidator → CashAvailabilityValidator → DailyLimitValidator. Each handler passes to the next or rejects.
ObserverHardware monitors observe cassette levels, paper status, and connectivity. Notify operations center on threshold breaches.
Template MethodBase Transaction.execute() defines the skeleton (validate → process → confirm → log), subclasses override specific steps.
SingletonBankNetwork connection pool - single managed instance per ATM.

Edge Cases

  1. Network Failure Mid-Transaction - If failure occurs after debit but before dispensing: the hold/debit is reversed via timeout or reconciliation batch. Transaction journal records the incomplete state for manual review.

  2. Cash Dispenser Jam - Sensors detect jam, ATM enters out-of-service state. If partial dispensing occurred, the transaction journal records exact notes dispensed for reconciliation. Customer is credited the undispensed amount.

  3. Partial Dispensing - Customer takes only some notes. Retract mechanism pulls back remaining notes after 30 seconds. Amount retracted is credited back. Full audit trail maintained.

  4. Power Failure - UPS provides 30 seconds to complete current transaction. Transaction journal (battery-backed NVRAM) ensures state is recoverable on restart. Incomplete transactions are reversed.

  5. Card Stuck in Reader - Mechanical retry (3 attempts). If unrecoverable, retain card, notify customer via screen, alert bank to disable card and schedule maintenance.

  6. Concurrent Withdrawal from Same Account - Bank's core system uses optimistic locking on account balance. Second ATM's debit request fails if balance is insufficient after first ATM's debit. Authorization holds prevent over-withdrawal.

  7. Daily Limit Across ATMs - Daily withdrawal counter maintained centrally at the bank, not at individual ATMs. Each withdrawal request includes cumulative check. Race condition handled by atomic increment at bank.

  8. Counterfeit Note in Deposit - Note validator rejects suspicious notes. Rejected notes returned to customer. Accepted notes counted and credited. Discrepancy resolved during back-office verification.

  9. Session Timeout During Dispensing - Timeout is suspended during active dispensing. Only applies during idle screens (selection, confirmation prompts).


Extensibility Points

  1. Cardless Withdrawal (QR/NFC) - Add AuthenticationStrategy interface. QR-based auth generates a one-time code via mobile app; NFC uses contactless card/phone. Existing state machine remains unchanged - only the AUTHENTICATING state gains new input methods.

  2. Multi-Language Support - Screen component uses a LocalizationService with language packs. Language selected at session start or from card preferences. All prompts are template-driven.

  3. Accessibility Features - Audio guidance via headphone jack, Braille on keypad, high-contrast screen mode, extended timeouts for visually impaired users. Triggered by headphone insertion or accessibility card flag.

  4. Cryptocurrency - Add new transaction type CryptoWithdrawal. Requires integration with crypto exchange API. Dispenses fiat equivalent or prints paper wallet. Extends the Transaction hierarchy without modifying existing types.

  5. Bill Payment - New transaction type with biller selection, account number input, and amount. Integrates with bill aggregator APIs. Fits naturally into the Command pattern.

  6. Biometric Authentication - Fingerprint or iris scanner as additional hardware component. Adds a step in the authentication chain (multi-factor).


Interview Follow-ups

Q1: How would you handle the scenario where cash is debited from the account but the dispenser fails to eject cash?

Answer: This is the most critical failure mode. The two-phase commit handles it:

  • Phase 1 places a hold (not a debit) on the account.
  • Cash is dispensed only after hold confirmation.
  • Phase 2 confirmation is sent only after dispenser sensors confirm cash was presented to the customer.
  • If dispensing fails, a cancellation message releases the hold.
  • If the ATM crashes between phases, the hold auto-expires (typically 5 minutes), and the reconciliation batch identifies orphaned holds for reversal.
  • The transaction journal in NVRAM records the exact state for dispute resolution.

Q2: How do you prevent the same card from being used simultaneously at two ATMs?

Answer: The bank's authorization system maintains a session lock per card. When an ATM requests PIN validation, the bank creates a session record. If another ATM attempts authentication with the same card, the bank either rejects it (strict mode) or allows it but uses optimistic locking on the balance for actual transactions. The first approach is simpler; the second allows balance inquiries from multiple locations. Most banks use the strict approach - one active ATM session per card at a time.

Q3: How would you design the cash dispensing algorithm to handle a request that cannot be fulfilled with available denominations?

Answer: Model it as a bounded knapsack problem:

  1. Check if the exact amount is achievable with available denominations using dynamic programming.
  2. If yes, apply the selected strategy (minimize notes or balanced).
  3. If no, suggest the nearest achievable amounts (round up and down) and let the customer choose.
  4. Maintain a pre-computed set of "dispensable amounts" that updates whenever cassette counts change, enabling instant validation without recomputation per request.

Q4: How would you design the system to work in regions with unreliable network connectivity?

Hint: Consider a store-and-forward architecture with local authorization rules. Think about risk scoring based on card history, withdrawal amount, and time since last online verification. What data would you cache locally, and how would you handle reconciliation conflicts?

Q5: How would you scale the monitoring system for 10,000+ ATMs reporting health metrics simultaneously?

Hint: Think about event-driven architecture with message queues. Consider hierarchical aggregation (ATM → regional collector → central dashboard). What metrics matter most for proactive maintenance vs. reactive alerts? How would you prioritize alerts when multiple ATMs report issues simultaneously?


Counter Questions to Ask Interviewer

Before diving into design, clarify scope with these questions:

  1. Scale: How many ATMs are we designing for? Single machine or the entire network management system?
  2. Bank Integration: Are we designing the ATM software only, or also the bank's backend authorization system?
  3. Hardware Abstraction: Should we model physical hardware components in detail, or treat them as black-box interfaces?
  4. Multi-bank Support: Does this ATM serve only one bank's customers, or is it shared (like white-label ATMs)?
  5. Regulatory Requirements: Are there specific compliance standards (PCI-DSS, RBI guidelines) we need to model?
  6. Failure Priority: What's more important - availability (allow risky offline transactions) or security (block everything when uncertain)?
  7. Scope of Transactions: Are we including advanced features (bill pay, mobile top-up, cardless) or focusing on core banking operations?
  8. Deployment: Is this a greenfield design or integration with an existing core banking system?

References

  1. Design Patterns: Elements of Reusable Object-Oriented Software - Gamma et al. (State, Strategy, Command, Observer patterns)
  2. PCI PIN Security Requirements - PCI Security Standards Council (PIN handling and encryption standards)
  3. ISO 8583 - Financial transaction card-originated messages (message format for ATM-bank communication)
  4. EMV Specifications - EMVCo (chip card authentication protocols)
  5. "ATM Software Architecture" - NCR Corporation technical documentation (real-world ATM software stack)
  6. Two-Phase Commit Protocol - Jim Gray, "Transaction Processing: Concepts and Techniques"
  7. XFS (eXtensions for Financial Services) - CEN/XFS standard for ATM hardware abstraction layer
  8. Head First Design Patterns - Freeman & Robson (accessible pattern explanations with ATM-like examples)


Implementation Considerations

Transaction Journal

The transaction journal is the ATM's most critical data structure. It resides in battery-backed non-volatile memory (NVRAM) and records every state transition:

[2024-01-15 14:32:01] ATM-5042 | SESSION_START | Card: ****4521
[2024-01-15 14:32:08] ATM-5042 | PIN_VALIDATED | Attempts: 1
[2024-01-15 14:32:15] ATM-5042 | TXN_INITIATED | Type: WITHDRAWAL | Amount: 5000
[2024-01-15 14:32:16] ATM-5042 | BANK_HOLD_OK | Auth: AX7291 | Hold: 5000
[2024-01-15 14:32:18] ATM-5042 | DISPENSE_START | Notes: 500x10
[2024-01-15 14:32:20] ATM-5042 | DISPENSE_COMPLETE | Sensor: ALL_TAKEN
[2024-01-15 14:32:20] ATM-5042 | BANK_CONFIRM | Auth: AX7291 | Status: SUCCESS
[2024-01-15 14:32:22] ATM-5042 | RECEIPT_PRINTED
[2024-01-15 14:32:25] ATM-5042 | SESSION_END | Card ejected

This journal enables:

  • Reconciliation - Match ATM records against bank records daily to identify discrepancies.
  • Dispute Resolution - Provide evidence when customers claim cash was not dispensed.
  • Crash Recovery - On restart, replay journal to determine last known state and complete or reverse pending transactions.

Security Architecture

The ATM security model operates in layers:

  1. Physical Security - Tamper-resistant safe for cash cassettes, anti-skimming devices on card reader, CCTV integration, vibration sensors for physical attacks.
  2. Communication Security - TLS 1.3 with mutual authentication (ATM certificate + bank certificate). All messages signed with HMAC-SHA256.
  3. PIN Security - PIN entered on encrypted pin pad (EPP) that encrypts at the hardware level. The ATM application never sees the plaintext PIN. Encrypted PIN block sent to bank's HSM for validation.
  4. Application Security - Hardened OS (typically embedded Linux or Windows IoT), application whitelisting, no USB ports exposed, remote attestation of software integrity.

Cassette Management

Each ATM typically has 4 cassettes with the following structure:

CassetteDenominationCapacityRefill Threshold
A₹20002,500 notes250 (10%)
B₹5002,500 notes250 (10%)
C₹2002,000 notes200 (10%)
D₹1002,000 notes200 (10%)

The dispensing algorithm must consider:

  • Current note counts per cassette
  • Predicted demand based on time of day and historical patterns
  • Minimum notes to reduce mechanical wear
  • Customer preference (some prefer smaller denominations)

Monitoring and Alerting

A centralized ATM monitoring system tracks:

  • Health Metrics - CPU temperature, memory usage, disk space, network latency
  • Operational Metrics - Transactions per hour, average transaction time, error rate
  • Hardware Status - Card reader jams, dispenser errors, printer paper level, cash levels
  • Security Events - Failed PIN attempts, skimming device detection, after-hours access

Alerts are prioritized: P1 (ATM down, security breach) triggers immediate response; P2 (low cash, printer issue) schedules next-day maintenance; P3 (performance degradation) feeds into weekly reports.


This problem tests understanding of state machines, hardware-software interaction, transaction safety, and real-world failure handling. Focus on the state diagram and two-phase commit during interviews - these demonstrate systems thinking beyond basic OOP. The combination of physical constraints (hardware failures, limited denominations) with distributed systems challenges (network partitions, concurrent access) makes this a rich problem for evaluating a candidate's breadth of knowledge.