Design a Reliable Bank Payment System
Company: J.P. Morgan
Role: Software Engineer
Category: System Design
Difficulty: medium
Interview Round: Onsite
# Design a Reliable Bank Payment System
Design a backend that accepts a customer's request to transfer money, tracks the payment through processing, and exposes its current status. The most important requirement is reliability: retries, crashes, duplicate requests, and uncertain responses from an external banking rail must not create an untracked or duplicated transfer.
Organize the design around requirements, API flow, data model, failure handling, and operations. Do not assume a particular transaction volume; explain which capacity facts would change your choices.
### Constraints & Assumptions
- A payment has a durable identity and an explicit state machine.
- Clients and internal workers may retry requests.
- An external processor can time out after accepting a request, leaving the local result uncertain.
- Money values use an exact representation and include currency.
- A user must be able to query a payment after the initial request returns.
### Clarifying Questions to Ask
- Is this an internal ledger transfer, an external bank transfer, or both?
- Which states and cancellation rules are visible to users?
- What consistency and completion-time expectations apply?
- Who is authoritative for final settlement, and how are disputes or reversals handled?
- What compliance, audit, retention, and regional constraints apply?
### Solving Hints
- Separate accepting an intent from completing an external side effect.
- Define retry behavior at every boundary, including the ambiguous timeout case.
- Treat reconciliation as part of the normal design, not an emergency-only tool.
### What a Strong Answer Covers
- Idempotent APIs, authentication, validation, and durable request acceptance.
- A transactional payment record, state-transition history, and an auditable money ledger where applicable.
- Asynchronous processing with an outbox or equivalent atomic handoff.
- Safe external-rail retries, provider idempotency keys, and an explicit unknown state.
- Reconciliation, invariant checks, alerting, and operator remediation.
- Data partitioning and availability choices that preserve correctness.
- Security, access control, encryption, auditability, and sensitive-data minimization.
### Follow-up Questions
1. What should happen when the processor times out but may already have sent the money?
2. How would you prevent two concurrent cancellation and completion requests from both succeeding?
3. Which invariants would you monitor continuously?
4. How would you migrate or shard the payment table without losing idempotency?
Quick Answer: Design a reliable bank payment system that remains correct across retries, crashes, duplicate requests, and ambiguous external-rail timeouts. Define idempotent APIs, a durable state machine and ledger, transactional handoff, safe reconciliation, invariant monitoring, auditability, and operator remediation.