System Design Interview Roadmap

System Design Interview Roadmap

System Design Walkthrough

Design Stripe Payments — The Senior+ Walkthrough

Jun 02, 2026
∙ Paid

This is the question that filters senior from staff in money-movement loops. The surface of the question — “design a payments processor” — looks ordinary. The probe underneath is one of the few places in system design interviews where being wrong has audit-trail consequences in production. Interviewers know this, which means they don’t accept the kind of hand-waving that flies on a feed-design question. You either understand idempotency, ledgers, and double-entry, or you don’t. The answer reveals it within five minutes.

If you are interviewing at Stripe, Block, Adyen, PayPal, Robinhood, Coinbase, or any fintech doing real money movement — this is the question. If you’re at FAANG-tier companies whose products handle payments (Amazon, Apple, Google), expect a variant. The frame is always the same: a customer initiates a payment, the system has to debit one party and credit another, and every single step has to be reconcilable, retryable, and auditable.

For L4 / mid-level the bar is the surface design. For L5 / senior, the probe is idempotency keys and the retry semantics around them. For L6 / staff, the probe is the ledger, double-entry consistency, and what happens when the upstream bank says yes-then-no.

The Question

“Design a payment processing service like Stripe. Customers (merchants) integrate your API to charge their end-users’ credit cards. The service handles the full flow: take card details, authorize the charge with the card network, settle the funds, and notify the merchant of the outcome.”

The question is rarely asked exactly this way. Common variants:

- “Design the core payment flow at a payments processor.”

- “Design a system to process credit card charges.”

- “How would you build the part of Stripe that charges a card?”

- “Walk me through what happens between stripe.charges.create() and money landing in the merchant’s account.”

All four are the same question. Don’t be thrown by the framing.

Step 1 — Clarify Before You Draw

Five questions before you draw anything. Each one is loaded.

1. Synchronous or asynchronous API? The merchant calls your endpoint and waits — or — the merchant gets a 202 Accepted and a webhook later? This single question determines half the architecture. Synchronous means your API call blocks on the card network round-trip (200ms–2s of bank latency on the hot path). Asynchronous means you queue the work and notify via webhook. Most production processors offer both modes; the synchronous mode is what merchants reach for first because it’s easier to integrate.

2. What payment instruments? Cards only, or also bank transfers, wallets, and BNPL? Pin this down. Cards only is a different design from “any payment method.” Cards have card networks (Visa/Mastercard/Amex). Bank transfers go through ACH (US), SEPA (EU), UPI (India), and have settlement windows of hours to days. BNPL (Klarna/Afterpay) involves a credit decision. Scope to cards for the core walkthrough; mention that a real system extends to other rails.

3. Are we issuing the cards, or just accepting them? Issuing cards (like Stripe Issuing or Cash App’s debit card) is a totally different system — you’re now responsible for card production, fraud on outbound spend, and chargebacks against your own balance. Accepting is what Stripe Payments does and what most candidates mean. Confirm scope explicitly.

4. Single currency or multi-currency? Multi-currency adds an FX layer, which adds rate-locking semantics (”the customer saw $20, but settle in EUR at what rate?”) and accounting complexity. Most candidates assume USD-only. State the assumption out loud.

5. What’s the SLO? Payment APIs typically target p99 < 500ms for the synchronous flow. And 99.99% availability — payments are revenue, downtime is direct loss for every merchant on the platform. State both numbers explicitly. They drive every later decision.

If you ask all five, you’ve already separated yourself from 80% of candidates. Most jump to drawing.

Step 2 — Estimate

Working assumptions for the rest of this walkthrough:

  • 10,000 transactions per second at peak. (Stripe processes more than this; pick a number

  • with a buffer.)

  • - 100 million transactions per day average; 500 million on peak shopping days.

  • - Average ticket: $50. So daily payment volume ~$5B at average, ~$25B at peak.

  • - 99.99% availability target = 52 minutes of downtime allowed per year.

  • - p99 latency target: 500ms for the synchronous charge endpoint.

Storage:

- Each transaction record is roughly 2 KB after enrichment.

- 100M/day × 365 = 36.5B transactions/year × 2 KB = ~73 TB/year.

- Retention: 7 years for financial records (PCI/regulatory). 7 × 73 = ~500 TB total.

This is big but not unprecedented. The implication: your transactional store is sharded relational (Postgres, Spanner, CockroachDB) and your archive is cold object storage with a hot/warm/cold tier. You won’t keep 7 years in your hot OLTP path.

Network: 10K tps × 2 KB = 20 MB/s. Trivial.

External dependencies — this is the unusual one for this question. You’re round-tripping to:

- Card networks (Visa, Mastercard) for authorization. ~200ms typical, can spike to 2s.

- Acquiring banks for settlement. Async; settlement is a batch process.

- Issuer banks for fraud signals. Sometimes inline, sometimes async.

- Fraud / risk services (could be in-house or external like Sift). ~50ms inline.

- Webhook delivery to merchants. Async, fire-and-forget with retry.

The interviewer will probe this list. Knowing the names of these systems is what separates a senior who has thought about payments from a candidate who’s read one blog post.

Get Access to GitHuB Repo

Step 3 — API Design

Three endpoints. The first one is where the round is decided.

POST /v1/charges

Headers:

Authorization: Bearer sk_live_xxx

Idempotency-Key: <client-generated UUID> ← THIS LINE IS THE PROBE

Body:

amount: integer (cents — never floats for money)

currency: string (ISO 4217: “usd”, “eur”)

source: string (tokenized card reference, e.g., “tok_xxx”)

description: string (optional)

metadata: object (merchant-defined)

Response: 200

id: “ch_xxx”

amount, currency, status: “succeeded” | “failed” | “pending”

outcome: { network_status, risk_level, seller_message }

GET /v1/charges/:id

Returns the current state of the charge. Idempotent by definition (HTTP GET).

POST /v1/refunds

Body:

charge_id: “ch_xxx”

amount: integer (defaults to full charge amount)

Idempotency-Key: <client-generated UUID>

Returns: { id: “re_xxx”, amount, status }

The senior move on this step: name the Idempotency-Key header out loud and explain why it’s there. Say something like: “Charging a card is the highest-stakes API call most companies ever make. Network failures, retries, double-clicks — all of these can cause the merchant’s code to call our endpoint twice with the same intent. We have to detect that and return the cached response instead of charging twice. This is what the Idempotency-Key header does.”

If you say that sentence in a Stripe interview, you’ve passed the first probe. If you don’t mention

idempotency by minute 10 of this question, you fail at minute 30 when the interviewer asks:

“What happens if the merchant’s code retries this call?”

Use integer cents, not floats. I’m calling it out because every junior candidate reaches for float for currency. Floating-point math has rounding errors. $0.10 + $0.20 ≠ $0.30 in IEEE 754. In production this causes accounting drift that takes weeks to find. Integer cents (or smaller — Stripe internally uses millicents for some flows) is the only correct answer. Saying this out loud is another senior signal.

Step 4 — Data Model

The OLTP record for the API call. Optimized for point lookups by id and by idempotency key.

Preparing for a distributed systems interview?
→Download the free Interview Pack
→ Subscribe now to access source code repository - 200 + coding lessons

User's avatar

Continue reading this post for free, courtesy of System Design Roadmap.

Or purchase a paid subscription.
© 2026 SystemDR Inc · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture