← Nubank Interview Insights

Nubank·Software Engineer·Onsite - System Design / Architecture·Senior

SeniorPrefer not to say
Jun 2026Remote

Summary

System design round at Nubank for a software engineering role. The whole thing was centered on one big problem: designing a chargeback ingestion and export system for a bank that ships CSV files to Mastercard over FTP four times a day. Dense question with a lot of moving parts.

Questions Asked (5)

Q1

Design a chargeback ingestion and export system for a bank that receives transaction records from internal systems, validates and stores them, then generates a CSV file and transfers it to Mastercard over FTP four times per day. Walk through the architecture, data model, batching strategy, reliability and idempotency guarantees, error handling, monitoring, and security.

System DesignData ModelingTechnical Trade-offs
Author's notes

I started with the architecture split and that was the right call.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then propose a high-level architecture that covers ingestion, validation, storage, batching, export, and transfer. Dive into each component, emphasizing reliability, idempotency, and security, and discuss trade-offs for key decisions.

Pro tip: Emphasize idempotency and exactly-once semantics in the context of financial systems, and discuss how you would handle partial failures and retries without duplicating data. Also, mention the importance of audit trails and compliance with financial regulations.

1. Clarify Requirements and Constraints

Ask questions to understand the volume of transactions, latency requirements, data sensitivity, and specific Mastercard FTP specifications. Clarify the expected failure modes and recovery time objectives.

2. High-Level Architecture

Outline the main components: ingestion API or message queue, validation service, storage (database and/or object store), batching scheduler, CSV generator, and FTP transfer service. Explain how they interact and scale.

3. Data Model and Storage

Design the schema for transaction records, including fields for chargeback data, status, timestamps, and idempotency keys. Discuss indexing, partitioning, and retention policies.

4. Batching, Export, and Transfer

Describe the batching strategy (e.g., time-based or size-based), CSV generation, and FTP transfer with retries. Explain how to ensure exactly-once delivery to Mastercard.

5. Reliability, Monitoring, and Security

Cover error handling, idempotency guarantees, monitoring/alerting, and security measures (encryption, access control, audit logs). Discuss trade-offs and failure recovery.

Key Points to Mention

  • Idempotency: Use unique transaction IDs and deduplication logic to handle retries without duplicating data.
  • Exactly-once semantics: Implement transactional outbox pattern or two-phase commit to ensure data is exported exactly once.
  • Batching strategy: Time-based batching (e.g., every 6 hours) with configurable size limits, and handling of late-arriving data.
  • Error handling: Retry with exponential backoff, dead-letter queues for failed records, and alerting on repeated failures.
  • Monitoring: Track ingestion rates, validation failures, batch success/failure, FTP transfer status, and end-to-end latency.
  • Security: Encrypt data at rest and in transit, use SFTP instead of FTP if possible, and implement strict access controls and audit logging.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

A scheduled batch's FTP upload fails all retries and misses its delivery window. What state is the batch in, what gets alerted, and how does the next run avoid double-sending or skipping those records?

System DesignRoot Cause AnalysisTechnical Trade-offs
Author's notes

This one I actually had a decent answer for.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the batch state after all retries fail and the delivery window is missed, then describe the alerting strategy, and finally explain the idempotent recovery mechanism for the next run. Emphasize how you prevent double-sending and skipping records through transactional state management and idempotency keys.

Pro tip: Mention that you would use a dead-letter queue or a failed state with manual intervention, and that idempotency is enforced at the record level, not just the batch level, to handle partial failures gracefully.

1. Define the batch state

After all retries fail and the delivery window is missed, the batch should transition to a terminal failed state (e.g., FAILED or DEAD_LETTERED) with metadata like failure reason, attempt count, and timestamp.

2. Alerting strategy

Trigger alerts to on-call engineers and business stakeholders via channels like PagerDuty, Slack, or email, including batch ID, affected records count, and impact on downstream systems.

3. Idempotent recovery for next run

Ensure the next run processes only records not yet successfully delivered by using a delivery status flag or idempotency key per record, and by querying the last successful checkpoint.

4. Prevent double-sending and skipping

Implement transactional updates: mark records as 'in-progress' before sending, then 'delivered' upon success; on failure, revert to 'pending' for retry. Use unique message IDs to deduplicate on the receiver side.

5. Monitoring and reconciliation

Add monitoring for batch success rates and reconciliation jobs to detect and correct any discrepancies between source and destination systems.

Key Points to Mention

  • Batch state machine with states like PENDING, IN_PROGRESS, FAILED, COMPLETED
  • Alerting with severity levels and runbook links
  • Idempotency keys or unique record IDs to prevent duplicates
  • Transactional outbox pattern or two-phase commit for exactly-once semantics
  • Checkpointing and resumability for large batches
  • Dead-letter queue for manual inspection and reprocessing

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

The upload to Mastercard completes successfully but your process crashes before it can record the success in your own database. On the next retry, how do you determine the file already arrived so you don't cause the partner to process it twice?

System DesignAPI & IntegrationsTechnical Trade-offs
Author's notes

Blanked for a second here.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Acknowledge the distributed systems nature of the problem and propose idempotency as the core solution. Explain how to use a unique idempotency key (e.g., file hash or transaction ID) that both parties can reference to detect duplicates. Then describe the reconciliation process on retry: query Mastercard's status API or check for an acknowledgment before re-uploading.

Pro tip: Emphasize that idempotency must be enforced on both sides—your system and the partner's—and that you should design for failure by persisting the idempotency key before the upload attempt. This shows you think about end-to-end reliability, not just your own service.

1. Identify the problem as a distributed transaction

Recognize that the crash creates an inconsistent state between your system and Mastercard, and that you need a way to reconcile without double-processing.

2. Introduce idempotency keys

Generate a unique key (e.g., UUID, file hash, or business transaction ID) for each upload attempt and persist it before sending. Include this key in the upload request so Mastercard can deduplicate.

3. Implement a status check or reconciliation API

On retry, first query Mastercard (or a shared ledger) using the idempotency key to check if the file was already processed successfully. Only re-upload if not found.

4. Design for failure with write-ahead logging

Before uploading, record the intent and idempotency key in your database. After upload, update the record with the outcome. This ensures you can recover state after a crash.

5. Discuss trade-offs and edge cases

Mention scenarios like network timeouts, partial failures, and the need for eventual consistency. Consider using a two-phase commit or saga pattern if applicable.

Key Points to Mention

  • Idempotency keys (e.g., UUID, file hash) to uniquely identify each upload attempt
  • Persisting the key and upload state before the network call (write-ahead logging)
  • Mastercard's API support for idempotency or a status query endpoint
  • Reconciliation logic on retry: check status before re-uploading
  • Trade-offs between strong consistency and availability (CAP theorem)
  • Handling edge cases like duplicate keys, timeouts, and partial failures

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Mastercard's acknowledgment file shows 3% of a batch was rejected due to a bad reason code. How do you reconcile this: how do those records get re-validated, re-queued, and exported without re-sending the accepted 97%?

Data ModelingSystem DesignRoot Cause Analysis
Author's notes

Reconciliation loop: parse the ack file, match rejected records by their IDs back to your DB, flip their status from 'exported' to 'rejected', re-validate them, fix the reason code if possible, and queue them for the next batch.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the reconciliation process: identify the rejected records, understand the reason code, correct the data, and re-validate them through the same validation pipeline. Then, ensure only the corrected records are re-queued and exported, using idempotent operations and tracking to avoid resending the accepted 97%.

Pro tip: Emphasize idempotency and traceability: use a unique batch ID and record-level status to ensure that re-processing only affects the rejected records, and log every step for auditability. This shows you understand the importance of not duplicating transactions in financial systems.

1. Identify and Extract Rejected Records

Query the acknowledgment file to isolate the 3% rejected records, capturing their unique identifiers and the specific reason code for rejection.

2. Analyze and Correct Root Cause

Investigate the reason code to determine if it's a data issue, formatting error, or business rule violation, then apply necessary corrections to the records.

3. Re-validate Corrected Records

Run the corrected records through the same validation logic to ensure they now pass all checks and meet Mastercard's requirements.

4. Re-queue and Export Only Corrected Records

Place the validated records into a new batch or queue, ensuring they are distinct from the original accepted records, and export them for submission.

5. Monitor and Confirm Acceptance

Track the new submission's acknowledgment to confirm the previously rejected records are now accepted, and update internal statuses accordingly.

Key Points to Mention

  • Idempotency: Ensure that re-processing does not create duplicates by using unique transaction identifiers.
  • Batch and record-level tracking: Maintain statuses (e.g., accepted, rejected, corrected) to avoid resending accepted records.
  • Root cause analysis: Understand why the reason code occurred to prevent future rejections.
  • Data validation: Re-run the same validation rules to ensure corrections are effective.
  • Audit trail: Log all actions for compliance and debugging.
  • Communication: Coordinate with Mastercard or internal teams if the reason code requires clarification or manual intervention.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

Daily volume grows 10x. Which components hit bottlenecks first, and how would you scale ingestion, validation, CSV generation, and transfer independently?

System DesignTechnical Trade-offsAdaptability & Ambiguity
Author's notes

Went through each layer.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by identifying the likely bottlenecks in each stage of the pipeline as volume grows 10x, then propose independent scaling strategies for ingestion, validation, CSV generation, and transfer. Emphasize decoupling components, using asynchronous processing, and leveraging horizontal scaling to handle increased load.

Pro tip: Demonstrate awareness of trade-offs: for example, scaling ingestion might involve partitioning and backpressure, while CSV generation could use parallel processing and streaming to avoid memory issues. Also, mention monitoring and metrics to detect bottlenecks early.

1. Identify bottlenecks

Analyze each stage (ingestion, validation, CSV generation, transfer) to determine which components will hit limits first as volume grows 10x. Consider CPU, memory, I/O, network, and database constraints.

2. Scale ingestion independently

Propose scaling ingestion by using message queues (e.g., Kafka) to buffer incoming data, partitioning by key, and adding consumer instances. Implement backpressure to handle bursts.

3. Scale validation independently

Decouple validation from ingestion by processing asynchronously. Use parallel validation workers, possibly with a stream processing framework (e.g., Flink) to validate in real-time or micro-batches.

4. Scale CSV generation independently

Generate CSVs in parallel by partitioning data and using distributed processing (e.g., Spark). Stream CSV writing to avoid memory bottlenecks and store outputs in object storage for scalability.

5. Scale transfer independently

Use parallel transfers with chunking and retries. Leverage CDNs or multi-threaded uploads/downloads, and consider compression to reduce bandwidth. Ensure transfer is decoupled from generation via queues or storage.

Key Points to Mention

  • Decoupling components with message queues or event-driven architecture to allow independent scaling.
  • Horizontal scaling (adding more instances) vs vertical scaling (bigger machines) and when to use each.
  • Partitioning and sharding strategies for data processing to enable parallelism.
  • Asynchronous and non-blocking I/O to improve throughput and resource utilization.
  • Monitoring and observability to identify bottlenecks and validate scaling efforts.
  • Trade-offs between consistency, latency, and cost when scaling each component.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.