Design a Payment Lifecycle from Hold to Charge and Settlement
OpenAISoftware Engineer · OnsiteLast updated
This problem tests the design of a distributed, idempotent payment processing system that ensures data consistency and financial integrity across asynchronous state transitions.
Problem Statement
Design a payment orchestration service that manages the lifecycle of a transaction from PENDING_HOLD to CHARGED and finally SETTLED. The system must interact with external payment gateways that are unreliable and often exhibit high latency.
Functional Requirements
- Lifecycle Management: Support transitions:
CREATED->HOLD->CHARGED->SETTLED(orFAILEDat any point). - Idempotency: Requests to charge or settle must be idempotent to prevent double-charging or inconsistent states when retrying after a gateway timeout.
- Accounting: Ensure every state change is recorded in an immutable ledger for audit purposes.
- Asynchrony: Handle external gateway responses asynchronously via webhooks or polling.
Constraints & Scale
- The system should handle 5,000 transactions per second (TPS) during peak hours.
- The system must prioritize financial accuracy over low-latency consistency (eventual consistency for reporting is acceptable, but transaction states must be strictly consistent).
- External gateways may return "In Progress" or "Unknown" statuses.
Deliverables
- Define the API endpoints for the client service to interact with your system.
- Propose a database schema for the
TransactionsandLedgertables. - Describe how you handle the "Unknown" state returned by a third-party processor.
- Sketch a high-level architecture, including how you ensure the atomicity of updating the transaction state and recording the ledger entry.
Hints
Hint 1
Use a state machine pattern to enforce valid transitions and ensure the current state is checked before any update.
Hint 2
Implement the 'Outbox Pattern' to ensure that state changes and ledger updates happen atomically or at least guarantee eventual consistency.
Hint 3
For the 'Unknown' gateway outcome, consider an inquiry mechanism (polling) paired with a TTL-based retry queue to reconcile the state.
Follow-up questions
- How would you handle a scenario where a user disputes a charge after it has been settled?
- What specific mechanisms would you use to reconcile your internal database against the bank’s daily settlement report (e.g., CSV files)?
- How would you scale the system if you needed to support multiple payment processors (Stripe, Braintree, etc.) with different API schemas?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.