Banking apps live at the intersection of high-stakes correctness and user experience. The interview tests whether you can design auth that is both secure and not user-hostile, transactions that cannot be lost or duplicated, and an experience that survives the sketchiest network conditions without compromising trust.
Functional requirements
- Login with biometrics or PIN — biometrics are the default happy path and PIN is the fallback when the sensor fails or after too many biometric misses. Interviewers probe how you rate-limit repeated PIN attempts and lock the account after N consecutive failures.
- View account balances and transactions — reads dominate this workload, so cache the latest balance and page transaction history from a ledger store with proper indexing. Be clear that you never serve a stale balance as if it were live.
- Transfer money between accounts and to other people — internal transfers settle instantly against your own ledger, while external transfers (ACH, wire, P2P) are asynchronous and can fail hours later. Model pending vs. settled states explicitly so the UI never implies a transfer is final before it clears.
- Pay bills — bill pay is a scheduled, often recurring transfer to a payee the user set up earlier. Expect questions on what happens when a payment date falls on a weekend or bounces for insufficient funds.
- Deposit checks via mobile camera — the interesting part is the client capturing a legible image and the backend clearing funds asynchronously, not instant credit. Call out duplicate-deposit detection so the same physical check can’t be submitted twice.
- Push notifications for transactions — these double as a trust signal, since a user seeing a charge they didn’t authorize is your fastest fraud tripwire. Keep the payload contentless and make the user open the app for details.
Non-functional
- Zero tolerance for lost or duplicated transfers — this requirement shapes the entire transaction design: every transfer carries an idempotency key and the server dedupes retries. Getting exactly-once semantics right is what makes this a favorite among system design interview questions, so be ready to defend at-least-once delivery plus server-side dedupe.
- Sub-second response for balance queries — balance reads are the most frequent operation, so serve them from a read-optimized cache and treat the ledger as the source of truth that reconciles behind it. Interviewers want to hear how the cache stays correct after a write.
- Strong auth: regulatory, biometric, MFA — regulations like strong customer authentication require two independent factors for high-risk actions. Be ready to name which factor is “something you have” (the enrolled device) vs. “something you are” (the biometric).
- PCI compliance and data-at-rest encryption — card data lives in a tokenized, scoped vault so most of your services never touch a raw card number. Encrypt everything else at rest and keep the keys in an HSM or managed KMS, not in the app config.
Auth flow
First-time setup:
- User logs in with username + password (server-side bcrypt or Argon2)
- Server returns a refresh token (long-lived, stored in iOS Keychain / Android Keystore)
- Client requests biometric enrollment — uses Touch ID / Face ID / Android Biometric to wrap the refresh token with a key tied to the secure enclave
Subsequent logins:
- User taps fingerprint/face → device unlocks the wrapped token → exchange for short-lived access token
- Access token (~15 min) signs API requests
- Sensitive operations (transfer over $X, change password) require step-up auth (PIN or fresh biometric)
Transaction flow
Critical path. Design for at-least-once delivery with idempotency:
- User taps “Send $100 to John”
- Client generates idempotency key (UUID)
- POST to
/transferswith idempotency key in header - Wait up to 10 seconds for response
- If timeout, retry with same key — server dedupes and returns existing transaction
- Show explicit “submitting” state, never optimistically confirm
- Confirmed only when server returns final transaction ID
Mobile check deposit
Camera-based:
- Capture front and back of check at high resolution (4K)
- Run on-device edge detection to crop to the check
- Show preview, let user retake if blurry
- Upload to server (encrypted in transit + at rest)
- Server runs OCR + fraud detection asynchronously
- Funds available 1–3 business days later
Push notifications
Push payloads do not contain sensitive data. Format: “Transaction posted to your account.” User opens app to see details.
Privacy mode: even less in the lock screen — “Update from [Bank Name].”
Offline behavior
Strict — banking is not offline-friendly. Disable transfers and bill pay when offline. Show last-known balance with a “as of [time]” disclaimer.
Security hardening
- Detect rooted/jailbroken devices and refuse to run — rely on platform attestation (Play Integrity / Apple App Attest) rather than easily-spoofed local checks, and decide up front whether a compromised device is hard-blocked or downgraded to read-only.
- Disable screenshots and screen recording on transfer screens — this blunts shoulder-surfing malware and screen-scraping overlays. On Android set FLAG_SECURE; on iOS blur the app snapshot in the app switcher.
- Cert pinning to prevent MITM — pin to your CA or leaf public key so a rogue root certificate installed on the device can’t intercept traffic. Ship a backup pin and a rotation plan so an expired cert doesn’t brick the app.
- Force re-auth after 5 minutes of inactivity — short session windows limit the damage from an unlocked, unattended phone. Step up with a biometric rather than a full password to keep it low-friction.
- Out-of-band fraud monitoring on the backend — score transactions server-side where the client can’t tamper with the logic. Flag velocity spikes, a brand-new payee paired with a max-amount transfer, and impossible-travel logins for review or step-up.
Frequently Asked Questions
How do you prevent a malicious app on the same device from reading your data?
iOS sandbox isolates app data; same on Android. Sensitive credentials in Keychain/Keystore, not on disk. Biometric-tied keys mean even root access on a jailbroken device cannot trivially extract them.
What if the user changes their fingerprint or face mid-session?
Biometric enrollment changes invalidate the key. User has to re-enroll with their password.
How do you handle ATO (account takeover) at the mobile layer?
Defense in depth: device fingerprinting, login geolocation anomalies, behavioral biometrics, MFA on suspicious logins, and out-of-band confirmation for high-value transfers.
Keep sharpening your system design:
