A timeout is not evidence that a payment failed
Your application submits a payment, the connection drops, and the customer presses the button again. You now have two questions: did the first operation take effect, and can the retry create another effect? A payment-system interview becomes interesting at this uncertainty boundary.
Stripe’s Payment Intent model tracks a payment through a lifecycle rather than treating it as a single synchronous Boolean result. Its idempotency contract provides a way to retry API operations with a stable key, subject to documented version and retention semantics. Build your answer around explicit state and identity instead of assuming an HTTP response describes the whole business outcome.
Scope the hypothetical product. Are you collecting subscription payments through a provider, managing a marketplace’s internal balances or building a regulated money-movement system? Those are materially different responsibilities. This guide focuses on engineering correctness with a provider and an internal ledger; it does not claim that a diagram satisfies financial licensing or compliance obligations.
Propose invariants: each logical operation has one stable identity; money entries are balanced within a defined currency ledger; displayed balances come from an explainable record; ambiguous external outcomes are reconciled; corrections preserve an audit trail. Ask which of these are required before choosing databases or message brokers.
Represent amounts and state transitions precisely
Record currency alongside every amount and define the unit. Stripe’s currency documentation explains minor-unit conventions and special cases. Do not assume every currency has two decimal places. Use an appropriate integer or decimal representation with validated bounds, and make conversion or rounding rules explicit at each interface.
Separate customer intent, provider state and internal accounting. An order says what the customer wants to buy. A payment attempt says what the application submitted. A provider object records external progress. A ledger entry records the accounting effect recognized internally. Collapsing them into one “paid” field makes partial failure hard to explain.
Write an illustrative state machine: requested, submitted, outcome unknown, confirmed, failed and reconciled. Specify allowed transitions and which evidence authorizes them. An expired HTTP request can move an attempt into “outcome unknown”; it should not automatically turn a provider operation into “failed.” Show that distinction in the user experience as well.
Define refund and dispute states separately from the original successful collection. A refund can have its own delay and failure outcome. Preserve references linking related operations, without editing history to pretend the original charge never existed. This gives support and engineering a common vocabulary when a customer asks why the displayed balance changed.
Make accounting effects durable and explainable
TigerBeetle’s financial-accounting guide describes accounts, debits and credits. Use that model to explain your internal ledger: a transfer moves an amount between defined accounts, and an accepted transaction preserves the specified balancing invariant. The chart of accounts should follow the product’s accounting model, developed with the appropriate domain owner.
TigerBeetle documents transfers as immutable records. A correction is represented by a new entry with a link to the original, rather than overwriting the original amount. That makes the sequence inspectable. If you implement a ledger in a relational database, explain which transactional constraints and access controls enforce the same intended properties.
Linked events in TigerBeetle support all-or-nothing handling of a linked chain, while two-phase transfers distinguish pending transfers from posting or voiding them. These are concrete mechanisms with documented semantics. Use them to motivate reservation and finalization when your hypothetical product needs both, rather than adding “pending” as an unexplained label.
Keep balance projections recoverable from the ledger or protected atomically with it. A cached balance must not become an independent source of truth whose updates can diverge silently. Explain the query pattern, concurrency control and reconciliation used to validate a projection. If performance requires additional state, describe the proof that it represents the same accepted entries.
Coordinate the provider without pretending it shares your transaction
A database transaction cannot atomically include a normal external payment request. Use a durable operation record and stable provider idempotency key. Commit the intent before submission, persist the provider reference when available and retry the same intended operation according to the provider’s rules. Do not generate a new identity merely because the original response was lost.
When a provider timeout leaves the outcome uncertain, query or reconcile the authoritative object before submitting a different operation. Separate safe retry from a new customer instruction. A repeated browser request with the same client key should map to the same intent and parameters; a materially different purchase requires a different identity.
Stripe webhook documentation warns about duplicates and ordering. Treat each verified event as durable input, deduplicate its identity and update business state conditionally. An event received later is not necessarily a later business transition. When necessary, consult the current authoritative provider object instead of applying arrival order blindly.
Use a transactional inbox for accepted events and an outbox for durable follow-up intents where appropriate. Then test a crash after the provider accepts a payment, after an event is received and after ledger entries commit. In each case, the durable operation and event identities should let a subsequent worker discover what remains, without issuing an uncontrolled second charge.
Reconciliation is a normal operating loop
Stripe’s balance-transaction taxonomy includes several kinds of movements, including charges, fees, refunds and disputes. A payment amount alone is not a complete settlement record. Define what you reconcile: customer payment states, internal accounting entries, provider balance movements or bank settlement. These comparisons have different units and timing.
For an illustrative daily reconciliation, compare internal operation references with provider records for the same account and interval. Match identities first, then amounts and currencies. Classify unmatched records, status disagreements and timing differences separately. An unresolved timing difference should not be silently erased by an adjustment designed only to make totals agree.
Persist the reconciliation run, input interval and exception decisions. Make rerunning the same interval safe. Corrections should cite the evidence and create the required accounting entries rather than changing past records. Give unresolved exceptions an owner, severity and escalation time based on the business consequence.
Report more than a grand total. Equal totals can conceal offsetting errors. Compare per-operation identity, currency and amount, then aggregate with an explanation of exclusions and timing. Avoid putting customer details into broad dashboards. Support needs a restricted view of the specific operation, while operators need coarse backlog and disagreement metrics.
Demonstrate one complete recovery path
Add one deliberately awkward accounting example to the rehearsal: a customer payment, a provider fee and a partial refund arrive as separate records. Show their identities and explain which internal accounts each affects. Do not net the three amounts into one unexplained balance update. If a scenario includes currency conversion, keep the original and converted currencies visible, define the rate and rounding rule for that operation, and explain which ledger owns each side. These are modeling choices to review with the accounting owner, not a claim that every payment product uses the same chart of accounts.
Practice a customer retry, a provider timeout, a duplicate webhook, an out-of-order status, a partial refund and a reconciliation mismatch. Label every amount in the example with currency and unit. These are hypothetical rehearsal cases, not a claimed payment failure rate or benchmark.
Trace the provider timeout all the way through the architecture: the intent exists, submission identity is stable, the outcome becomes unknown, a worker queries the provider, verified confirmation authorizes ledger effects and reconciliation checks the resulting records. Then ask what happens if each step loses its response.
Explain the operating limits. Which team can create adjustments? What requires review? How are sensitive records protected? What is the recovery path if the provider is unavailable for an extended period? You do not need to invent legal requirements; you do need to identify where engineering correctness and domain obligations require collaboration.
A strong payment design makes uncertainty visible and recoverable. Its ledger explains recognized money movements, its operation identities prevent uncontrolled retries and its reconciliation loop finds disagreement before someone solves it with a spreadsheet overwrite. Practice that argument in Interview Copilot before expanding the diagram into more services.
Practice the reasoning behind your next interview
Use Interview Copilot to prepare questions and rehearse clear answers. Keep assessed interviews within the employer’s stated tool and assistance rules.
Create a free account