SYSTEM-DESIGN Contents

Design Payment System

Design secure and reliable payment processing.

On this page

Problem Statement

Design a payment system that safely creates charges, handles retries, prevents duplicates, and records immutable ledgers. The system must prioritize correctness and auditability over raw throughput.

Functional Requirements

  • Create payment intents / charges
  • Confirm and capture payments
  • Handle refunds and chargebacks
  • Maintain a ledger for auditing

Non-Functional Requirements

  • Strong correctness (no double charge, no lost charge)
  • Idempotent APIs for client retries
  • Auditability and immutable history
  • Secure handling of sensitive data

Idempotency Is Mandatory

Clients will retry on timeouts. Every write endpoint must accept an idempotency key and return the same result for the same key within a defined window. This prevents duplicate side effects even under replay.

Ledger as the Source of Truth

Use an append-only ledger for financial events. Do not “update balances” directly as the primary record; compute balances from ledger entries or maintain derived balances with strict reconciliation.

Workflow and State Machine

Payments are multi-step. Model states explicitly (created, authorized, captured, failed, refunded). Enforce valid transitions and make each transition idempotent.

External Provider Integration

Payment providers can be slow or return ambiguous outcomes. Handle “unknown” states by recording pending status and reconciling via webhooks and periodic polling. Never assume a timeout means failure.

Security Constraints

Use tokenization and avoid storing raw card data. Encrypt at rest and in transit. Strictly control access to keys and secrets. Redact logs aggressively.

Production-First Takeaway

Payment systems are correctness-first. Design idempotency into every write, maintain an immutable ledger, model states explicitly, and reconcile external ambiguity with webhooks and controlled retry logic.