System requirements
Functional:
- User Account Management: Allow users to create, update, and delete their accounts, as well as manage personal details and payment methods.
- Fund Transfers: Enable users to send and receive payments to/from other users with the ability to input amounts and confirm transactions.
- Payment Processing: Facilitate smooth transactions, including processing card payments, bank transfers, and various electronic payment methods.
- Fraud Detection: Implement mechanisms to analyze transactions for potential fraudulent activities to protect users.
- Buyer and Seller Protection: Ensure measures are in place to safeguard both buyers and sellers, including dispute resolution and refund policies.
- Multi-Currency Support: Allow transactions in different currencies with real-time conversion rates.
- Transaction History: Provide users with a detailed history of their transactions, including amounts, dates, and transaction status.
- Notifications: Send real-time notifications regarding transaction status, security alerts, or promotional offers.
- API Integration: Offer APIs for third-party developers to integrate payment processing into their platforms easily.
- Security Measures: Ensure secure transactions with encryption, two-factor authentication, and compliance with payment regulations.
Non-Functional:
- Scalability: The system should handle a growing number of users and transactions without performance degradation. For instance, it should support up to 1 million transactions per day initially with the capacity to scale as the user base grows.
- Reliability: The system should ensure high availability (e.g., 99.9% uptime) to allow users to access and transact with minimal disruptions. This may involve implementing redundancy and failover mechanisms.
- Performance: Transactions should be processed in a timely manner, ideally within a few seconds. The system should be able to handle concurrent transactions efficiently.
- Security: The system must comply with security standards (e.g., PCI DSS) to protect user data and prevent unauthorized access, ensuring encryption of sensitive information and secure APIs.
- Usability: The interface should be intuitive and user-friendly so that users can navigate easily and complete transactions with minimal effort.
- Maintainability: The system should be designed for easy updates and maintenance, allowing developers to modify components without affecting overall system performance.
- Compliance: The service must comply with financial regulations and data protection laws across different regions (e.g., GDPR, CCPA).
- Localization: The system should support multiple languages and currencies to cater to a global user base.
- Interoperability: The payment service should be able to integrate easily with existing banking systems and third-party applications.
- Monitoring and Logging: There should be mechanisms in place for comprehensive logging and monitoring of transactions and system performance for audit trails and troubleshooting.
Capacity estimation
Starting: 100000 Users/day
50000 transactions per day
10GB of transactions daily
1 server can do 1000 conections
1 server can hold 1000GB of data
Having those numbers we can estimate the resources we need:
1) RPS = 50000 RPD / 24 * 60 * 60 = 0.57 RPS
2) Connections per second = 10000 / 24 * 60 * 60 = 1.15
3) Data to store per year = 10GB * 365 = 3650GB
4) Servers to serve connections = 10000 users/day / 1000 = 10 servers
5) Servers to hold data = 3650 / 1000 = 4 servers (round up)
API design
GET /v1/account
POST /v1/account
PATCH /v1/account
POST /v1/transfer
GET /v1/payLink
GET /v1/history
GET /v1/audit/logs
Database design
User <|-- UserWallet
User : +int UserId INDEX
User : +String UserName
User : +String HashedPassword
User : +String Email INDEX
User : +DateTime CreatedAt
UserWallet <|-- User
UserWallet : +int WalletId INDEX
UserWallet : +int UserId INDEX
UserWallet : +int Balance
UserWallet : +int CurrencyCode
Transaction <|-- User
Transaction <|-- PaymentType
Transaction <|-- TransactionType
Transaction : +int TransactionId INDEX
Transaction : +int UserIdFrom INDEX
Transaction : +int UserIdTo INDEX
Transaction : +int TransactionType
Transaction : +int PaymentType
Transaction : +int Amount
Transaction : +int CurrencyCode
Transaction : +DateTime Date
Transaction : +String Message
CurrencyConversionRate <|-- Currency
CurrencyConversionRate : +int ID
CurrencyConversionRate : +int FromId
CurrencyConversionRate : +int ToId
CurrencyConversionRate : +float Multiplier
CurrencyConversionRate : +DateTime timestamp INDEX
FraudLog <|-- Transaction
FraudLog : +int ID INDEX
FraudLog : +int TransactionId INDEX
FraudLog : +DateTime TimeStamp INDEX
Paymentbackend : +int ID
Paymentbackend : +String Name
PaymentbackendDetails <|-- Paymentbackend
PaymentbackendDetails : +int ID
PaymentbackendDetails : +int PaymentBackendId
PaymentbackendDetails : +int SupportedPaymentType
PaymentType : +int ID
PaymentType : +String Name
Currency : +int ID
Currency : +String Name
TransactionType : +int ID
TransactionType : +String Name
High-level design
1) Api gateway/load balancer
2) User service
3) Payment service
4) Log infra and audti services
5) Payment backend
6) Transaction processor
Request flows
1) User issues an HTTP request to transfer funds
2) Request goes through api gateway/load balancer
3) Request goes into payment service
4) Payment service calls payemnt backedn and stores transaction in db
5) Payment service issues notification to a client
Detailed component design
1) Payment service: accepts payment requests from client and coordinates payment processros to execute payment backends. Performs risk checks for transations using FraudService and records transactions in durable manner into Transaction DB. ALso notifies client about success using Notification Service
2) User service. Manages user accounts. Stores relevant user info in database and provides API to manage an account
3) Log service. Samples health logs from all system components (except self) and stores them in a log database. Also allows to perform a fulltext search on the logs and sends notification when a new log is encountered
4) Audit infra. Monitors the health of underlying services and sends notifications using Notification Service if health parameters drop with limit
5) Transaction read replica. Responsible for serving transaction writes to the user. Used to optimize read-heavy path of retrieving transaction info.
Trade offs/Tech choices
Predominance of Reads
- User Account Information:
- Path:
GET /v1/account - Expected Reads: The user profile and balance check are common operations. Users may frequently access their account details without triggering many updates.
- Optimization: Use caching for user profiles and balances (e.g., Redis) to reduce database load.
- Path:
- Transaction History:
- Path:
GET /v1/history - Expected Reads: Users will query their transaction history often to verify payments and balances.
- Optimization: Implement pagination and caching strategies to improve response times and reduce database querying overhead.
- Path:
- Payment Links:
- Path:
GET /v1/payLink - Expected Reads: Many users may request payment links for different transactions.
- Optimization: Cache frequently generated links or store them temporarily in a quick-access database.
- Path:
- Currency Conversion Rates:
- Path: Could be an endpoint like
GET /v1/currency/rates. - Expected Reads: Currency rates are often read for each transaction and may not change frequently.
- Optimization: Store rates in a high-speed cache and limit updates perhaps hourly or daily.
- Path: Could be an endpoint like
Predominance of Writes
- User Account Creation/Updates:
- Path:
POST /v1/accountandPATCH /v1/account - Expected Writes: These paths involve high write operations for user creation and metadata updates.
- Optimization: Validate inputs at the application layer to ensure that only necessary data modifications are made.
- Path:
- Fund Transfers:
- Path:
POST /v1/transfer - Expected Writes: This is a critical path where each transaction results in multiple writes, including creating transaction records and updating user wallet balances.
- Optimization: Use an asynchronous processing model (e.g., message queues) to manage transactional writes to the database and ensure transactional integrity.
- Path:
- Logging Transactions:
- Path: Writing logs to
Log Infrastructure - Expected Writes: Each transaction may generate multiple log entries for security and auditing. This creates a significant amount of write operations.
- Optimization: Batch log entries to write in groups to reduce write frequency and thus improve performance.
- Path: Writing logs to
- Fraud Detection Logs:
- Path: Writing to
TransactionFraudLog - Expected Writes: When an unusual transaction is detected, it would lead to numerous write operations.
- Optimization: Ensure that the fraud detection system is efficient at batching operations to avoid overwhelming the logging infrastructure.
- Path: Writing to
Handling failed transactions
Handling failed transactions in a payment system is crucial for ensuring reliability and fault tolerance. Here's how we can tackle these challenges based on the provided information:
Tracking Payment State:
- Definitive Payment State: Maintaining a definitive payment state at every stage of the payment cycle enables us to determine the current state of a transaction in case of failure.
- Persistence: Persisting payment states in an append-only database table ensures that transaction status can be accurately tracked and managed.
1) Transaction log is a read heavy system that prioritize availability thus we choose some no-sql solution for easy scaling like cassandra or amazon dynamo db
2) Logging system is write heavy with strong avaialbilty a thus we prioritize sharding our log database based on service (user service, payment service, etc) For reading when the amount of logs is too big we use pagination to retrieve only latest logs. For DB with use some NoSQL solution optimized for high writes
3) User management system is not read or write heavy and case use classic SQL solution and be sharded by user ID when the amount of users get too big
4) To insure durability of our transaction log we maintain a write ahead log that records all action applications before flushing them to db.
5) To scala the payment processros we use queu technology like apache kafka.
Failure scenarios/bottlenecks
Retry Queue and Dead Letter Queue:
- Retry Queue: Retryable errors, such as transient network issues, are routed to a retry queue for subsequent retry attempts.
- Dead Letter Queue: Messages that fail repeatedly end up in the dead letter queue, facilitating debugging and isolation of problematic messages for inspection.
Retry Strategies:
- Immediate Retry: Resending the request immediately upon failure.
- Fixed Intervals: Waiting a fixed amount of time between the failed payment and subsequent retry attempts.
- Incremental Intervals: Gradually increasing the time between retry attempts.
- Exponential Backoff: Doubling the waiting time between retries after each failed attempt to prevent overwhelming the system with retry attempts.
- Cancellation: Canceling the request if the failure is deemed permanent or if repeated attempts are unlikely to succeed.
Example of Retry:
- Scenario: A client attempts to make a $10 payment, but the request fails due to a poor network connection.
- Retry Attempts: The client retries the payment request multiple times until the network connection eventually recovers, ensuring the transaction's successful completion.
- Retry Interval Decision: Deciding appropriate time intervals between retries is crucial to balance between ensuring transaction success and avoiding overwhelming the system with retry attempts.
Future improvements
Use ML for fraud detection