Back to System Design

SYSTEM DESIGN · QUESTION 109

How would you design a reliable payment processing system?

On this page
Advanced 4 min read
Interview-ready answerThe concise version to remember

I would clarify payment methods, authorization versus capture, refunds, consistency, and audit needs. Create a durable payment intent with an idempotency key, validate the request, and coordinate provider calls through explicit states and an outbox or workflow. Handle timeouts as unknown outcomes, reconcile with the provider, and keep an immutable ledger. Never assume a network retry means the first attempt failed.

LET'S MAKE IT SIMPLE

First, the idea in plain English

A payment request may reach a provider even if the response gets lost. If the application retries as a new charge, the customer may be charged twice. The system needs a stable payment identity, clear state transitions, and reconciliation for cases where the result is uncertain.

A USEFUL COMPARISON

Picture it this way

A bank transfer receipt has a transaction reference so the bank can check whether a request already happened after a connection drops. The system must distinguish “not processed” from “processed but response missing.”

FOLLOW THE JOURNEY

Track payment intent and reconcile uncertain provider outcomes

Show idempotent request handling, provider interaction, state transitions, and ledger recording.

Track payment intent and reconcile uncertain provider outcomesShow idempotent request handling, provider interaction, state transitions, and ledger recording.Payment state flow
01Create intentValidate amount, currency, identity, and idempotency key.
02Call provider safelyAuthorize or capture with bounded timeouts and provider idempotency.
03Record state and ledgerPersist transitions and immutable financial entries.
04Reconcile and notifyQuery provider status and publish confirmed outcomes.

This simplified visual highlights the main relationships. In practice, the exact design depends on the requirements; Do not infer success or failure from a missing response.

A client creates an idempotent payment intent; a workflow calls a payment provider, records authorization or uncertainty, reconciles status, and posts ledger entries.

How to read this visual
This simplified visual highlights the main relationships. In practice, the exact design depends on the requirements; Do not infer success or failure from a missing response.

UNDER THE HOOD

How it works, step by step

01

Create intent

Validate amount, currency, identity, and idempotency key.

Why it matters: A stable intent anchors retries and audit.

02

Call provider safely

Authorize or capture with bounded timeouts and provider idempotency.

Why it matters: Network failure may leave the outcome unknown.

03

Record state and ledger

Persist transitions and immutable financial entries.

Why it matters: Financial history needs traceability and reconciliation.

04

Reconcile and notify

Query provider status and publish confirmed outcomes.

Why it matters: Do not infer success or failure from a missing response.

OUTSIDE THE TEXTBOOK

A practical example

A customer submits a card payment and the provider times out after receiving it. The service marks the attempt as pending or unknown, then checks provider status using the same idempotency key before retrying. It posts a ledger entry only from a confirmed state and communicates the eventual result.

GO A LITTLE DEEPER

Technical details that matter

  • Payment intent state machines should make valid transitions explicit and auditable.
  • The transactional outbox can ensure database state and event publication remain consistent.
  • A ledger records balanced immutable entries; corrections are represented as compensating entries rather than rewriting history.

MAKE A GOOD CHOICE

When is this useful?

  • Checkout, subscriptions, transfers, and refunds.
  • Any workflow with external financial side effects and retries.
  • Systems requiring audit trails and reconciliation.
Consider the alternative

Use a trusted payment processor’s hosted checkout when it meets product requirements and reduces sensitive-card-data handling.

WATCH OUT FOR

Common misunderstandings

  • Retrying a timed-out charge with a new request identity.
  • Treating authorization as settlement or capture.
  • Updating balances without a durable ledger and reconciliation process.

REAL-WORLD TRADE-OFFS

Limitations and failure cases

  • Provider outcomes can remain unknown temporarily.
  • Financial workflows require strict audit, privacy, and compliance controls.
  • Cross-system transactions are not generally atomic.

WHAT TO REMEMBER

Key takeaways

  1. 1Use durable payment intents and idempotency keys.
  2. 2Treat timeouts as uncertain until reconciled.
  3. 3Maintain explicit states, immutable ledger entries, and provider reconciliation.

PRACTICE THE FOLLOW-UP

What might an interviewer ask next?

What should happen after a provider timeout?

Keep the outcome pending or unknown, then query or reconcile with the provider using the same idempotency identity before attempting another charge.

Why use a ledger?

It provides an auditable history of financial changes and supports reconciliation; balances can be derived or checked against entries.

SAY IT OUT LOUD

How to explain this in an interview

“I would model a durable payment intent with an idempotency key and explicit authorization, capture, refund, and failure states. A timeout is an unknown outcome, not proof the provider did nothing, so I reconcile before retrying. I keep an immutable ledger and audit trail, and publish confirmed outcomes through a reliable workflow.”

Continue your learning path

Connect this question to the roadmap topic it supports.

Open roadmap topic