Bird
Raised Fist0
LLDsystem_design~7 mins

Transaction history in LLD - System Design Guide

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Problem Statement
When users perform multiple operations like payments or transfers, losing the record of these actions causes confusion and disputes. Without a reliable transaction history, users cannot verify past activities or detect errors, leading to trust issues and operational failures.
Solution
Maintain an ordered log of all transactions with details such as timestamp, amount, and status. This log acts as a single source of truth for all past operations, allowing users and systems to review, audit, and reconcile activities accurately.
Architecture
User App
Transaction
Audit & Reporting
Audit & Reporting

This diagram shows a user app sending transaction requests to a transaction service, which records them in a transaction history database. An audit service reads from this database for reporting and verification.

Trade-offs
✓ Pros
Provides a clear, immutable record of all user transactions for auditing and dispute resolution.
Enables easy rollback or reconciliation by referencing past transaction states.
Improves user trust by allowing transparent access to their transaction history.
✗ Cons
Storing detailed history increases storage requirements over time.
Maintaining consistency and ordering can add complexity in distributed systems.
Querying large histories may require indexing or archiving strategies to maintain performance.
Use when the system handles financial or critical user operations requiring audit trails, especially when transaction volume exceeds hundreds per second and regulatory compliance is needed.
Avoid if the system only performs simple, stateless operations with no need for historical audit or if transaction volume is extremely low (under 10 per minute) where overhead outweighs benefits.
Real World Examples
Stripe
Keeps detailed transaction histories for all payment operations to enable dispute resolution and compliance with financial regulations.
Amazon
Maintains order and payment transaction logs to track purchases, refunds, and account activities for customer service and auditing.
PayPal
Records every money transfer and payment event to provide users with a complete transaction history and fraud detection.
Code Example
The before code processes payments without saving any record. The after code adds a TransactionHistory class that stores each payment with details and timestamp. The PaymentProcessor uses this to save every transaction, enabling retrieval of user transaction history.
LLD
### Before: No transaction history tracking
class PaymentProcessor:
    def process_payment(self, user_id, amount):
        # Process payment logic
        print(f"Processed payment of {amount} for user {user_id}")


### After: With transaction history tracking
from datetime import datetime

class TransactionHistory:
    def __init__(self):
        self.records = []

    def add_record(self, user_id, amount, status):
        record = {
            'user_id': user_id,
            'amount': amount,
            'status': status,
            'timestamp': datetime.utcnow().isoformat() + 'Z'
        }
        self.records.append(record)

    def get_history(self, user_id):
        return [r for r in self.records if r['user_id'] == user_id]

class PaymentProcessor:
    def __init__(self, history):
        self.history = history

    def process_payment(self, user_id, amount):
        # Process payment logic
        status = 'success'  # Assume success for example
        self.history.add_record(user_id, amount, status)
        print(f"Processed payment of {amount} for user {user_id}")

# Usage
history = TransactionHistory()
processor = PaymentProcessor(history)
processor.process_payment('user123', 100)
print(history.get_history('user123'))
OutputSuccess
Alternatives
Event Sourcing
Stores all changes as a sequence of events rather than just final transaction records, enabling full state reconstruction.
Use when: Choose when you need full auditability and the ability to rebuild system state from events.
Snapshotting
Periodically saves the current state to reduce the need to replay the entire transaction history.
Use when: Choose when transaction history grows large and replaying all events becomes inefficient.
Summary
Transaction history prevents loss of critical operation records and supports auditing and dispute resolution.
It works by recording every transaction with details and timestamps in a consistent log.
This pattern is essential for financial systems and any application requiring reliable operation tracking.

Practice

(1/5)
1. What is the main purpose of a transaction history in a system?
easy
A. To record all important actions with details for tracking
B. To speed up the system by caching data
C. To delete old data automatically
D. To encrypt user passwords

Solution

  1. Step 1: Understand the role of transaction history

    Transaction history stores records of actions with details like timestamps and IDs.
  2. Step 2: Identify the correct purpose

    This helps users and systems track past events clearly and reliably.
  3. Final Answer:

    To record all important actions with details for tracking -> Option A
  4. Quick Check:

    Transaction history purpose = record actions [OK]
Hint: Transaction history = record actions with details [OK]
Common Mistakes:
  • Confusing transaction history with caching
  • Thinking it deletes data automatically
  • Mixing it with security features like encryption
2. Which of the following is the correct way to uniquely identify each transaction in a history system?
easy
A. Using a timestamp only
B. Using a unique transaction ID
C. Using the user's name
D. Using the transaction amount

Solution

  1. Step 1: Identify unique identifiers in transaction history

    Unique transaction IDs ensure each record is distinct and traceable.
  2. Step 2: Compare options

    Timestamps alone can repeat; user names and amounts are not unique identifiers.
  3. Final Answer:

    Using a unique transaction ID -> Option B
  4. Quick Check:

    Unique ID = unique transaction record [OK]
Hint: Unique transaction ID ensures distinct records [OK]
Common Mistakes:
  • Assuming timestamp alone is unique
  • Using user name as unique key
  • Using transaction amount as identifier
3. Given this simplified transaction record list:
transactions = [
  {"id": "t1", "time": "2024-01-01T10:00:00Z"},
  {"id": "t2", "time": "2024-01-01T09:00:00Z"},
  {"id": "t3", "time": "2024-01-01T11:00:00Z"}
]

What is the correct order of transaction IDs if sorted by time ascending?
medium
A. ["t1", "t2", "t3"]
B. ["t2", "t3", "t1"]
C. ["t3", "t1", "t2"]
D. ["t2", "t1", "t3"]

Solution

  1. Step 1: Analyze timestamps for each transaction

    t2 = 09:00, t1 = 10:00, t3 = 11:00 in UTC time.
  2. Step 2: Sort transactions by ascending time

    Order is t2 (earliest), then t1, then t3 (latest).
  3. Final Answer:

    ["t2", "t1", "t3"] -> Option D
  4. Quick Check:

    Sorted by time ascending = [t2, t1, t3] [OK]
Hint: Sort by timestamp ascending for correct order [OK]
Common Mistakes:
  • Sorting by ID instead of time
  • Confusing ascending with descending order
  • Ignoring timestamp format
4. You have this code snippet to add a transaction record:
def add_transaction(history, transaction):
    if transaction['id'] not in [t['id'] for t in history]:
        history.append(transaction)
    else:
        print("Duplicate transaction")

history = [{"id": "t1"}]
add_transaction(history, {"id": "t1"})

What is the output when running this code?
medium
A. Duplicate transaction
B. KeyError exception
C. No output, transaction added
D. TypeError exception

Solution

  1. Step 1: Check if transaction ID exists in history

    The code checks if 't1' is already in the list of IDs in history.
  2. Step 2: Since 't1' exists, print duplicate message

    The else branch runs and prints "Duplicate transaction".
  3. Final Answer:

    Duplicate transaction -> Option A
  4. Quick Check:

    Duplicate ID detected = print message [OK]
Hint: Check for existing ID before adding to avoid duplicates [OK]
Common Mistakes:
  • Assuming transaction is added anyway
  • Expecting an exception instead of print
  • Confusing list comprehension syntax
5. You want to design a scalable transaction history system for millions of users. Which approach best ensures fast retrieval of a user's transactions sorted by time?
hard
A. Store transactions in separate files per day without indexing
B. Store all transactions in one big list and scan it every time
C. Use a database with an index on user ID and timestamp
D. Keep transactions only in memory without persistence

Solution

  1. Step 1: Consider scalability and retrieval speed

    Scanning one big list or files without index is slow for millions of users.
  2. Step 2: Use database indexing on user ID and timestamp

    This allows fast queries to get transactions per user sorted by time efficiently.
  3. Step 3: Avoid in-memory only storage for persistence and scale

    Memory-only storage risks data loss and limits scale.
  4. Final Answer:

    Use a database with an index on user ID and timestamp -> Option C
  5. Quick Check:

    Indexing = fast retrieval at scale [OK]
Hint: Index on user ID and timestamp for fast queries [OK]
Common Mistakes:
  • Scanning large lists for each query
  • Ignoring indexing benefits
  • Relying on memory-only storage