🎓 A1Learner
🔍
0 of 64 lessons completed

Design a Payment System

A payment system is the service that moves money from a payer to a payee through banks and card networks. Every move is written in a ledger, a permanent record book of money in and money out.

The ask

A payer is the person or business sending money. A payee is the person or business receiving it.

The system takes a pay request, checks that the payer can pay, and moves the amount.

Settlement is the final movement of money between banks after a payment is approved. A payment can be approved at once and settled later.

Refunds, payment status and receipts belong inside the design. Lending and credit decisions stay outside it.

Correctness matters more than speed. A lost payment and a doubled payment are both failures.

Estimate the scale

The design handles 100,000,000 payments a day.

100,000,000 / 86,400 = 1,157 payments per second on average.

Peak load runs at 3 times the average. 100,000,000 x 3 / 86,400 = about 3,472 payments per second at peak.

The average payment is 50 units. 100,000,000 x 50 = 5,000,000,000 units move through the system a day.

Money movement is small data with huge trust. The write rate is modest and the record must be exact.

API and data

The main operation is pay. It carries a payer, a payee, an amount in units and an idempotency key.

An idempotency key is a value the client sends with a request. A repeat with the same key returns the first result and does not pay again.

Other operations read payment status, issue a refund and list the payments for one account.

A ledger is the permanent record book for money. Every account balance can be rebuilt from its entries.

Double entry is the rule that every payment writes two ledger entries. One entry shows money leaving one account and the other shows money arriving in another account.

Every payment writes 2 ledger entries. 100,000,000 x 2 = 200,000,000 entries a day.

High-level design

An app server receives the pay request and validates the fields. Bad amounts and missing accounts fail fast.

A fraud check is a named component that takes payment facts and returns a risk score. Its inner model stays outside the design and a high score routes the payment to human review.

A payment service talks to banks and card networks through connectors. Each connector hides one outside network behind the same shape.

Approved payments write their two entries to the ledger store. The ledger store is the heart of the system.

A queue carries later work such as settlement files and receipts. Slow later work never blocks the payer.

Deep dive: money moves once

A network timeout leaves a hard doubt. The bank may have taken the money while the answer was lost.

The idempotency key answers that doubt. A retry carries the same key and the bank connector returns the stored result.

Each payment moves through clear states in plain words. It starts as received, then checked, then approved or refused, then settled or failed.

A state is stored before the next outside call is made. A crash then resumes from the stored state instead of starting again.

Reconciliation compares the ledger with bank records on a schedule. Any gap raises a case for a person to resolve.

200,000,000 entries a day at 200 bytes each give the storage size. 200,000,000 x 200 = 40,000,000,000 bytes, which is 40 GB of ledger a day.

Deep dive: the Kindle storefront

The Kindle case is a single storefront selling reading devices and books. One storefront takes every payment itself instead of serving many sellers.

That storefront takes 1,000,000 payments a day. 1,000,000 / 86,400 = 12 payments per second.

The rate is small and the spine stays the same. The pay request, the fraud check, the bank connector and the ledger all remain.

Its ledger still uses double entry. 1,000,000 x 2 = 2,000,000 entries a day.

What shrinks is capacity, not care. Fewer connectors, fewer app servers and a smaller ledger store carry the same rules.

Failures and retries

A bank can be down while payers keep arriving. Requests wait in a queue with their keys, and status reads show them as pending.

A refund is a new payment in the other direction. It writes its own two entries and never edits the old ones.

Ledger entries are never changed after writing. A mistake is fixed by a new correcting entry, so the full story stays visible.

Duplicates are expected from retries and are safe by design. The key, the stored state and the ledger together stop a second move.

Scaling the ledger

The ledger is partitioned by account. All entries for one account sit on one shard, so a balance rebuild reads one place.

Writes are appends, so each shard takes a steady stream of new entries. Reads for status and history follow replicas.

Hot accounts get their own shard when shared shards grow busy. A shop account and a person account follow the same rule.

Settlement work reads finished payments in batches. Batch reads run away from the live write path.

Evaluation and trade-offs

Strong consistency wins for the ledger. A balance read after a payment must reflect that payment.

Speed gives way at the bank edge. Outside networks answer slowly, and the design waits or queues instead of guessing.

The gain is a record that can be proved. Any payment can be traced from request to entries to settlement.

The cost is care at every step. States, keys, reconciliation and correcting entries are the price of moving money once.

Scale at a glance

MeasureValue
Payments a day100,000,000
Average rate1,157 per second
Peak rateabout 3,472 per second
Ledger entries a day200,000,000
Ledger growth a day40 GB

Exercise

Why does every payment write two ledger entries?