Diagrammatic

Design and Implement a Wire Transfer API — System Design Interview Practice

Design a secure API for bank wire transfers with compliance and fraud detection. Work through the requirements, architecture trade-offs, and an interactive design review.

Concepts and architecture decisions to consider

  • paymentsConcept to explore
  • wire transferConcept to explore
  • financialConcept to explore
  • securityConcept to explore
  • complianceConcept to explore

Interview prompt

Design a secure wire-transfer API for domestic and international payments with beneficiary verification, sanctions/fraud controls, multi-step approval, settlement tracking, and immutable auditability.

  • Define transfer intent/state machine, source/destination accounts, beneficiary, limits, fees/FX, compliance decisions, settlement, returns, and idempotency.
  • Keep ledger reservation and authorization correct while external bank rails remain asynchronous; reconcile unknown outcomes rather than retrying blindly.
  • Separate API orchestration from double-entry ledger, sanctions/fraud checks, bank adapters, approvals, notifications, and reconciliation.
  • Explain maker-checker controls, encryption, audit retention, provider failure, duplicate messages, privacy, observability, and pending status.

Requirements and scale assumptions

  • Create and authorize domestic/international transfers, verify beneficiaries, screen sanctions/fraud, reserve funds, submit to rails, and track settlement.
  • Support approvals, fees/FX, cutoff windows, status webhooks, returns/recalls, reconciliation, statements, and compliance reporting.
  • Make retries idempotent, preserve a balanced ledger and audit trail, enforce role limits, and recover safely from rail timeouts or duplicates.
  • Return an accepted/pending/failed result within two seconds while guaranteeing no duplicate debit or credit ledger effect.
  • Scale to 1M transfers per day across accounts and corridors without a single hot key or unbounded synchronous work.
  • Do not lose committed state; make retries and duplicate events safe.
  • Degrade safely when downstream workers, caches, or external dependencies fail.
  • 1M transfers/day, 100k webhook events/hour, and multi-currency corridors
  • Partition by the primary tenant, user, item, or geographic key and isolate hot partitions.
  • Keep serving state bounded; retain raw events or durable records for replay and auditing.
  • Peak scale: 1M transfers/day; 100k webhooks/hour — Capacity assumption that drives partitioning and backpressure.
  • Latency target: decision < 2s; ledger effects exactly once — User-facing budget for the primary request or read path.
  • Durable boundary: Committed before async — The double-entry ledger, transfer state, and rail reconciliation records are authoritative.
  • Async boundary: At-least-once workers — Keep Event sourcing for audit trail, Saga pattern for distributed transactions, Machine learning for fraud detection off the synchronous path.

Key entities

  • PaymentIntentintentId, merchantId, amount, currency, status, version, idempotencyKey

    Versioned state machine for an authorized and implement a wire transfer api money movement.

  • LedgerEntryentryId, intentId, accountId, direction, amount, currency, createdAt

    Append-only double-entry record for the financial effect of and implement a wire transfer api.

  • ProviderAttemptattemptId, intentId, provider, requestHash, status, providerRef

    Retry-safe external attempt with an unknown-outcome reconciliation path.

  • SettlementRecordsettlementId, intentId, batchId, gross, fees, status

    Reconciled and implement a wire transfer api settlement and discrepancy state.

Data flow

  1. 1. Create an idempotent financial intentThe and implement a wire transfer api gateway authenticates the merchant, validates amount and currency, tokenizes the instrument reference, and records the idempotency key.
  2. 2. Authorize and capture safelyThe orchestrator advances the and implement a wire transfer api state machine with conditional writes and creates exactly one ledger effect for each business transition.
  3. 3. Resolve external outcomesProvider responses and webhooks are stored as immutable attempts; timeouts remain unknown until and implement a wire transfer api reconciliation resolves them.
  4. 4. Publish status asynchronouslyAn outbox emits committed and implement a wire transfer api events for merchant status, risk, notifications, and settlement without blocking the financial commit.
  5. 5. Reconcile and repairSettlement jobs compare provider reports, ledger entries, and internal intents; discrepancies become auditable repair tasks rather than silent edits.

Deep dives and trade-offs

  • Exactly-once financial effectsUse the idempotency key at the API, orchestrator, provider-attempt, and ledger boundaries. Make capture, refund, reversal, and cancellation transitions conditional on the current intent version. Treat provider timeouts as unknown and resolve them through status lookup or signed webhook reconciliation.
  • Ledger and reconciliation correctnessKeep and implement a wire transfer api ledger entries append-only and derive balances or views from them. Reconcile gross amount, fees, currency, provider reference, and settlement batch with tolerances that are explicit. Never repair by deleting history; append a compensating entry and preserve the operator reason.
  • Risk, privacy, and availabilityKeep and implement a wire transfer api instrument data tokenized and minimize PCI or sensitive-data scope. Apply risk decisions before irreversible effects and make provider failover policy explicit. Expose pending and unknown states instead of retrying blindly or showing a false success.
  • Single provider versus multi-provider routingStart with one provider behind an adapter and add routing only when availability, geography, or cost justifies it. Failing over an unknown and implement a wire transfer api outcome can double-charge unless reconciliation proves the first attempt’s result.
  • Synchronous confirmation versus asynchronous completionReturn a durable pending state quickly and complete provider, webhook, and settlement work asynchronously. Holding an HTTP request open across provider and risk systems creates ambiguous retries and poor tail latency.
  • Ledger-first versus provider-first stateMake the internal intent and ledger the source of truth for recorded effects while treating provider state as an external fact to reconcile. Letting a provider response directly mutate balances bypasses audit and correction controls.
Diagrammatic — system design practice and architecture review.