← Questions

Keep a shared payment account correct under concurrent payments

0
TeslaSystem designLast asked Jul 2025

Two people share one online payment account and both pay with it at the same moment. Design the payment flow so the balance is never wrong: no double spending, no lost updates, no payment applied twice. Answer from the API side and from the data side, then explain how the design holds up under a very large number of requests.

The same screen moves on to quick technical questions: the HTTP methods you use most and why; how relational and NoSQL databases differ; and whether and how you use Kubernetes (deployments, services and ingress, autoscaling, configuration and secrets, observability, rollbacks and upgrades).

Requirements

  • Functional: debit the shared balance for a payment; reject a payment the balance cannot cover; show both users a correct balance and history.
  • Non-functional: strong consistency for the balance; retries from flaky clients must not double-charge; high throughput across many accounts; auditable history.

Clarifying questions

  • Can the balance go negative (overdraft), or must every payment be fully covered?
  • Is the balance held by us, or are we calling an external bank or card network?
  • How many payments per second overall, and per account at peak?
  • What should the second payer see when the first payment uses up the balance?

What a strong answer covers

  • API: an idempotency key per payment request, stored with the result, so a retry returns the same outcome; POST to create a payment, GET to read; clear error codes for insufficient funds.
  • Data: a ledger of entries plus a balance, updated in one transaction; either a row lock (SELECT … FOR UPDATE), an atomic conditional update (UPDATE … SET balance = balance - x WHERE balance >= x), or optimistic concurrency with a version number and retry.
  • Why reading the balance, checking it in application code and then writing it is a race.
  • Scale: shard by account so contention stays inside one account; a hot shared account can serialize through a queue per account; idempotency-key storage with a TTL; reconciliation of the ledger against the balance.
  • For the quick questions: GET/POST/PUT/PATCH/DELETE and which are idempotent; relational (schemas, joins, transactions) vs NoSQL (flexible schemas, horizontal scale, weaker or tunable consistency) and when each fits; concrete Kubernetes use with a specific problem you solved.

Follow-ups

  • The payment calls an external processor that may time out. How do you avoid charging twice?
  • One account receives thousands of payments per second. What changes?
  • How do you roll out a schema change to the ledger with no downtime?
Your canvas
Draw your answer hereBoxes, arrows and notes, saved for you to come back to.Sign in to start drawing