// Interview Prep/Industry Questions/Fintech QA

🔵 Fintech QA

11 questions · full model answers. Ledger correctness, idempotency, and regulatory hard-fails — testing where money must be exactly right, immutable, and auditable.

// What they weigh

What a Fintech QA interviewer is actually probing for — beyond generic QA.

  • 01

    Money exactness and ledger correctness

    In fintech, money must be exactly correct, not approximately. Reconciliation against the provider's statement is a first-class test, and every state change is immutable and auditable.

  • 02

    Idempotency and async provider lag

    Provider confirmation lags create premature-success windows, and retries create duplicate-charge risk. Interviewers want idempotency keys and pending-state discipline.

  • 03

    Regulatory hard-fails

    KYC/AML gates, transaction limits enforced at the API, and PCI rules on logging are legally mandated. Strong candidates treat them as non-negotiable correctness conditions and never use real credentials in test.

  • 04

    Core banking and lending mechanics

    Beyond payments, banking adds calendar-driven and stateful correctness: interest accrual under the right day-count convention, amortisation and repayment allocation, and account lifecycle rules where a closed or dormant account must never silently accept a posting.

// Junior · 1

What's the difference between authorisation and capture in a payment, and how would you test each?

Junior

Authorisation reserves funds; capture actually moves them. Test each phase independently, including auth-without-capture, capture failure after a good auth, and expiry of an uncaptured authorisation.

// What interviewers look for

That payment is a two-phase operation with independent failure points, and that the gap between auth and capture is where money-state bugs live.

Common pitfall

Treating a payment as one atomic event, so the auth-succeeded-but-capture-failed state (and the orphaned hold on the customer's funds) is never tested.

Model answer

Authorisation is the provider confirming and reserving the funds; capture is the later step that actually settles them. They're separate calls that can fail independently, so I test them separately. For authorisation: a valid auth places a hold, a declined card returns the right error, and an auth that's never captured eventually expires and releases the hold. For capture: capturing a valid auth settles the correct amount, a partial capture settles less than authorised (e.g. a partial shipment), capturing more than authorised is rejected, and a capture attempted after the auth expired fails cleanly. The interesting state is auth-succeeded, capture-failed — the customer sees a hold but no completed transaction — so I assert the system surfaces and reconciles that rather than stranding a phantom hold. Throughout, I use only sandbox test cards, never real credentials.

paymentsauthorisationcapturetwo-phase

// Mid-level · 4

A payment request times out and the client retries it. How do you test that the customer isn't charged twice?

Mid-level

Submit the same payment twice with an identical idempotency key and assert exactly one charge is created at the provider and one ledger entry is written.

// What interviewers look for

Idempotency framed around the charge and the ledger: the key dedupes the financial side effect, and you test it under genuine retry/timeout conditions, not just a clean resend.

Common pitfall

Confusing this with webhook dedupe, or assuming a timeout means the charge didn't happen — a timed-out request can have succeeded at the provider, so a naive retry double-charges.

Model answer

A network timeout is ambiguous — the charge may have gone through — so the client must retry safely, and the mechanism is an idempotency key. I'd send the same payment body twice with the same key and assert exactly one charge at the provider and one ledger entry, with the second call returning the original result rather than creating a new one. I'd test the timing race: two requests with the same key arriving nearly simultaneously must still produce one charge, so I fire them in parallel. I'd test that different payments with different keys both go through, and that a reused key with a different amount is rejected rather than silently returning the old charge. This is specifically about the money side effect and the ledger write being deduplicated; it's distinct from webhook idempotency, which is about inbound event delivery. Sandbox provider only, no real cards.

idempotencypaymentsledgerretry

A 2.9% processing fee is applied to a $0.01 transaction. How do you test the rounding and fee calculation?

Mid-level

Assert the minimum-fee floor is applied rather than rounding to $0.00, and test sub-cent amounts across the fee formula since rounding errors compound across millions of transactions.

// What interviewers look for

Domain-specific rounding reasoning: the minimum-fee floor, banker's vs naive rounding, and the fact that tiny per-transaction errors aggregate into real money at scale.

Common pitfall

Treating it as a generic boundary-value exercise and missing the fee floor — letting a percentage fee round to $0.00 and processing the transaction at a loss.

Model answer

The trap is that 2.9% of $0.01 rounds to $0.00, so I assert the minimum-fee floor (say $0.30) is applied instead — the transaction either carries the floor fee or is rejected per the product rule, never processed at a loss. I'd build a small matrix of fractional amounts and fee percentages and check each against the documented rounding rule, watching for the boundaries where rounding flips a cent. Because these errors compound, I'd also run an aggregate check: process a large batch and reconcile that the summed fees match the expected total to the cent, catching drift that's invisible per-transaction. I'd cover currency-specific rules — currencies with no minor unit, three-decimal currencies — and FX-converted amounts where rounding happens twice. The distinction from a generic boundary question is that the domain rules (minimum floor, compounding, reconciliation to the cent) drive the cases, not just min/max inputs.

roundingfeescurrencyreconciliation

How would you test daily reconciliation between the internal ledger and the payment provider's statement?

Mid-level

Run a batch of known transactions, then assert the internal ledger total exactly matches the provider's sandbox statement — any discrepancy is a bug, not a report line.

// What interviewers look for

That reconciliation is a correctness test, not optional reporting: you make the diff deterministic with seeded balances and treat any drift as a defect to root-cause.

Common pitfall

Viewing reconciliation as a finance/reporting concern outside QA, or not seeding known starting balances so the comparison is non-deterministic.

Model answer

I treat reconciliation as a first-class test: at the end of a run, the internal ledger must match the provider's statement exactly, and any difference is a defect. To make it deterministic I seed known starting balances and run a controlled set of transactions — successes, failures, refunds, fees — then pull the provider sandbox statement and diff line by line and on the total. I specifically test the edge cases that cause real drift: a failed transaction that still deducted a fee, a webhook that arrived after the reconciliation window closed (it must queue to the next cycle, not vanish), a refund that updated order status but not the ledger, and timezone/cutoff mismatches where a transaction lands in the wrong day. I'd automate the diff in CI so any drift fails the build with the offending entries surfaced. The mindset is that the ledger is the source of truth and reconciliation is how we prove it, every day.

reconciliationledgerbatchcorrectness

How would you test that transactions are handled correctly across account lifecycle states — dormant, reactivated, and closed?

Mid-level

Seed accounts in each lifecycle state and assert state-specific handling: a posting to a dormant account triggers the defined reactivation path, a posting to a closed account is rejected or routed to suspense, and residual balances are handled per policy on closure.

// What interviewers look for

Treating the account as a state machine with distinct posting rules per state — dormant, frozen, and closed are different — and knowing a closed account must never silently accept funds.

Common pitfall

Testing only active-account happy paths, or conflating dormant/closed with the AML-frozen block — so a credit to a closed account is silently applied and the money is stranded with no suspense entry.

Model answer

I model the account as a state machine — open, active, dormant, frozen, closed — and test the posting rules at each state plus the transitions between them, because each state has different correct behaviour. For dormant: an account with no activity past the dormancy threshold should be marked dormant, and an inbound posting should follow the defined path — typically reactivation, where I assert the account flips back to active, the transaction applies, and an audit entry records the reactivation. For closed: a posting must not silently succeed; per policy it's either rejected with a clear error or routed to a suspense account so the funds stay traceable, and I assert one of those happens, never a silent apply to a closed balance. Closure itself needs the residual-balance test: closing an account with a non-zero balance must sweep or refund the residual per policy rather than orphaning it, and a closure attempt with funds still present behaves deterministically. I cover the transition races too — a transaction in flight when the account is closed or marked dormant, and a reactivation that coincides with an incoming batch posting. I deliberately keep this separate from the AML-frozen case, which is a compliance hard-fail on an otherwise-live account; here the concern is the lifecycle of the account itself and where money goes when the account is not in a normal state. Synthetic accounts only, seeded directly into each state so I don't have to wait out real dormancy windows.

core bankingaccount lifecyclestate machine

// Senior · 4

A payment shows 'success' to the customer, but the provider declines it three seconds later via webhook. How do you catch this premature-success bug?

Senior

Delay the provider webhook with a stub and assert the payment status stays 'pending' until confirmation arrives — it must never flip to 'success' on submission alone.

// What interviewers look for

Understanding of provider confirmation lag: the internal state must not run ahead of the external truth, and a pending state is the correct intermediate, not optimistic success.

Common pitfall

Allowing the UI/state to mark success on submit for responsiveness, which gives the customer access to funds or goods before the provider has actually confirmed.

Model answer

The bug is the internal state getting ahead of the provider's truth. I'd stub the provider to delay the confirmation webhook by a few seconds and assert that during that window the payment is 'pending' — not 'success' — and the customer doesn't yet get access to funds or fulfilment. When the webhook arrives as a decline, the state must resolve to failed and any provisional access is revoked; when it arrives as success, it resolves to success. I'd test the opposite ordering too: a webhook that arrives before the synchronous response completes. The anti-pattern I'm hunting is optimistic success on submit done for UI responsiveness, because in fintech that means showing money the provider never confirmed. So I assert the system models an explicit pending state and only transitions on the authoritative event, with WireMock giving me deterministic control over the lag.

asyncwebhooksstatuspending state

Transaction limits (per-transaction, daily, cumulative) pass in the UI. How do you prove they actually hold?

Senior

Call the transfer API directly, bypassing the UI, at exactly the limit, one below, and one above for each limit type — and assert an over-limit call returns a proper error (e.g. 422), not a 200.

// What interviewers look for

That limit enforcement must live at the API, with boundary testing for each limit dimension. This echoes RBAC-at-API but the concern is a monetary ceiling, not a permission.

Common pitfall

Trusting UI validation. A direct API call that skips the front-end check will submit an over-limit transaction if the server doesn't independently enforce the ceiling.

Model answer

UI validation is a convenience; the enforcement boundary is the API, so I call the transfer endpoint directly with a valid token and skip the front-end entirely. For each limit dimension — single-transaction, daily aggregate, cumulative — I test the boundary triple: one below (allowed), exactly at (per the inclusive/exclusive rule), and one above (rejected). An over-limit call must return a precise error like 422 with a limit-exceeded code, never a 200 or a 500. The aggregate limits need stateful setup: I seed prior transactions so the next one crosses the daily or cumulative threshold, and I check the window boundary — does 'daily' reset at UTC midnight or local, and what happens to an in-flight transaction across the reset. It's structurally like proving RBAC at the API, but here the gate is a monetary ceiling rather than a role, and the failure is regulatory/financial rather than access-control.

limitsapiboundarycompliance

How do you test KYC/AML hard-fail paths safely — for example, that a flagged account can't move money?

Senior

Seed synthetic accounts in each KYC/AML state and assert a flagged account is blocked even via a direct API call, using only fabricated identity data — never real credentials or PII.

// What interviewers look for

Treating compliance gates as hard, API-enforced fails, plus the data-handling discipline of synthetic-only test data for regulated identity flows.

Common pitfall

Testing only the UI block, or — worse — using real identity/financial data in a test environment, which is itself a compliance violation.

Model answer

I'd seed synthetic accounts representing each state: verified, pending, rejected, expired KYC, and AML-flagged — all with fabricated identifiers, because using real PII or credentials in a test environment is itself a breach. Then I assert the hard-fail holds at the data/API layer: a flagged or unverified account cannot initiate a transfer even through a direct API call with a valid auth token, returning a clear blocked status. I'd test the lifecycle transitions: a document that expires mid-flow, a verification that flips from pending to rejected, and a flag applied to an account with an in-flight transaction. I'd confirm every access to an identity document writes an audit entry. The two things I'm signalling are that compliance gates are non-negotiable server-side fails, not UI hints, and that regulated test data must be synthetic by construction.

kycamlcompliancesynthetic datasecurity

How would you test daily interest accrual on a savings account across a leap year, with a rate change mid-cycle?

Senior

Seed a known principal and a dated rate schedule, then assert daily accrual against a golden expected-accrual table — splitting the calculation at the rate-change date, using the correct day-count convention, and including the leap-year extra day.

// What interviewers look for

Domain mechanics: day-count conventions (ACT/360 vs 30/360 vs ACT/365), the leap-year day, splitting accrual at a rate-change boundary, and the compounding base — not generic number rounding.

Common pitfall

Treating it as fee rounding or a single flat-rate calculation, so the day-count convention, the Feb-29 day, and the mid-cycle rate split are never isolated — accrual drifts a little every day and compounds over the term.

Model answer

Interest accrual is a per-day calculation, so I test it day by day against a golden table rather than checking one end balance. I seed a known principal, a documented day-count convention (say ACT/360), and a rate schedule with a defined change date, then compute the expected accrual for each day independently and assert the system matches to the minor unit. The convention is the first trap: ACT/360 divides actual days by 360, 30/360 normalises every month to 30 days, ACT/365 uses the real year length — each gives a different daily figure, so I parametrise the suite over the conventions the product supports. The leap year is the second: across a period containing Feb 29 I assert the extra day accrues under ACT conventions and is handled per spec under 30/360. The mid-cycle rate change is the third: accrual must split at the change date, the old rate applying up to the boundary per the inclusive/exclusive rule and the new rate after, so I place rate changes on a month boundary, on Feb 28→29, and on the compounding date to catch off-by-one-day errors. I also assert the compounding base — does interest compound on principal only or on principal-plus-accrued — and reconcile the summed daily accruals against the posted interest at cycle close. This is explicitly not fee rounding; the cases are driven by calendar and rate-schedule mechanics, not by min/max input values.

core bankinginterestlendingday-count

// Lead · 2

Design a test strategy that guarantees financial correctness across a release.

Lead

Make reconciliation, idempotency, the rounding matrix, and audit-log completeness hard release gates, layered from fast contract tests up to a thin sandbox E2E, with no release on any failing gate.

// What interviewers look for

A correctness-first, gate-based strategy specific to money: which checks block a release, how they're layered for fast feedback, and how audit/compliance are built in rather than bolted on.

Common pitfall

A generic test-pyramid answer that doesn't name the fintech-specific gates (reconciliation drift, idempotency, rounding, audit completeness) as the things that actually block shipping.

Model answer

In fintech the release question is 'can we prove money is exactly right', so I'd define hard gates that block shipping: reconciliation diff is clean against the sandbox statement; idempotency holds (duplicate request and duplicate webhook each produce one record); the rounding matrix passes including the minimum-fee floor; audit-log completeness is verified for every financial and permission event; and a PCI log scan finds no card data. I'd layer these for feedback speed — unit/property tests for rounding and fee math, contract tests at the provider boundary for idempotency and status mapping, integration tests for ledger writes and limits, and a thin E2E that runs the full payment → webhook → ledger → balance path in sandbox. Compliance is designed in: synthetic-only data, audit assertions in the suite, limits tested at the API. Every gate has an unambiguous pass/fail, and any red gate stops the release — correctness outranks velocity here.

strategycorrectnessreconciliationgatesaudit

How do you test FX rate handling when the exchange rate at transfer time differs from the rate at settlement time?

Lead

Assert the rate is locked at transfer time and used consistently through settlement — never silently re-fetched — and test the timezone/cutoff boundaries where settlement crosses into a new rate day.

// What interviewers look for

Awareness that FX introduces a time dimension to correctness: the quoted rate must be captured and honoured, and double-rounding plus day-boundary cutoffs are where money leaks.

Common pitfall

Assuming a single live rate. If settlement re-fetches the rate, the customer is charged a different amount than quoted, and double conversion compounds rounding error.

Model answer

FX adds a time axis to correctness, so the core assertion is that the rate quoted and locked at transfer time is the rate used at settlement, even if settlement happens hours or days later when the market rate has moved. I'd capture the locked rate, move the simulated clock and market rate forward, settle, and assert the customer's amount matches the original quote — no silent re-fetch. I'd test the rounding carefully because conversion plus fee plus reconciliation can round more than once; I assert the documented order of operations and reconcile to the cent. Day-boundary cases matter: a transfer quoted just before the rate-day cutoff settling after it, and timezone mismatches between the quote service and the ledger (UTC vs local). I'd also cover an expired quote — if the lock window lapses before settlement, the system must re-quote explicitly, not quietly apply a new rate. The signal is that in cross-currency flows, 'when' is as load-bearing as 'how much'.

fxcurrencysettlementtime

// Go deeper

These questions pair with the in-depth Fintech QA QA guide — the risk areas, signature bugs, and test strategies the questions are drawn from.