← Wells Fargo Interview Insights

Wells Fargo·Software Engineer·Onsite - System Design / Architecture·Senior

SeniorPrefer not to say
May 2026

Summary

System design round at Wells Fargo for a software engineer role. The whole thing was one big design problem about building a document aggregation service that calls three downstream APIs and survives partial failures. Felt like a pretty senior-level question for the title they were hiring at.

Questions Asked (7)

Q1

Design the write path for a document aggregation service that fans out to three independent downstream APIs, combines the results, and persists the bundle. Where does the orchestration logic live?

System DesignAPI & IntegrationsTechnical Trade-offs
Author's notes

This is the core of the whole question.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then propose a layered architecture where orchestration lives in a dedicated service or workflow engine. Discuss trade-offs between synchronous fan-out with parallel calls and asynchronous event-driven orchestration, and justify your choice based on latency, reliability, and complexity.

Pro tip: Emphasize idempotency and partial failure handling—downstream APIs can fail independently, so design for retries, timeouts, and compensating actions. Mention that in a regulated environment like Wells Fargo, auditability and data consistency are critical, so consider using a saga pattern or transactional outbox.

1. Clarify Requirements and Constraints

Ask about expected latency, throughput, consistency needs, and failure tolerance. Confirm whether the three APIs are synchronous or asynchronous, and if the bundle must be persisted atomically.

2. Choose Orchestration Location

Decide between choreography (each service reacts to events) and orchestration (a central coordinator). For fan-out/fan-in with persistence, a dedicated orchestrator service or workflow engine (e.g., Temporal, AWS Step Functions) is usually clearer.

3. Design the Write Path

Outline the sequence: receive request, persist initial state, fan out parallel calls to downstream APIs, aggregate responses, and persist the final bundle. Include idempotency keys and deduplication.

4. Handle Failures and Consistency

Describe retry policies, circuit breakers, timeouts, and dead-letter queues. For partial failures, decide whether to fail the whole bundle or store partial results with a status flag.

5. Address Scalability and Observability

Discuss horizontal scaling of the orchestrator, backpressure, and monitoring. Include logging, tracing, and metrics for each downstream call and the aggregation step.

Key Points to Mention

  • Orchestration vs. choreography trade-offs: central coordinator simplifies complex flows but can become a bottleneck; choreography is more decoupled but harder to reason about.
  • Idempotency and exactly-once semantics: use idempotency keys to avoid duplicate writes when retrying.
  • Partial failure handling: use timeouts, retries with exponential backoff, and circuit breakers; consider storing partial results with a status.
  • Data consistency: use transactions or sagas to ensure the bundle is persisted atomically or with compensating actions.
  • Scalability: design the orchestrator to be stateless and horizontally scalable; use async processing if latency allows.
  • Observability: implement distributed tracing, logging, and metrics to monitor each downstream call and the aggregation.

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

Q2

How does your design handle one or more of the three downstream calls timing out or returning an error? Walk through transient vs persistent failure and how every request reaches a terminal state.

System DesignTechnical Trade-offsRoot Cause Analysis
Author's notes

Circuit breakers per downstream, retries with backoff and jitter, dead letter queue for exhausted retries.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the design's failure-handling strategy: timeouts, retries with backoff, circuit breakers, and fallbacks. Then distinguish transient failures (retryable) from persistent failures (fail fast, degrade gracefully), and explain how every request reaches a terminal state via success, fallback, or error response. Use a concrete example to illustrate the flow.

Pro tip: Emphasize idempotency and observability: ensure retries are safe and log/metric every failure path so you can diagnose issues. This shows you think about production readiness, not just theoretical correctness.

1. Define failure modes and timeouts

Identify what constitutes a timeout or error for each downstream call, and set appropriate timeout values based on SLAs. Mention that timeouts should be shorter than the overall request deadline to leave room for fallbacks.

2. Classify transient vs persistent failures

Explain how to distinguish transient failures (e.g., network blips, 5xx errors) from persistent ones (e.g., 4xx errors, repeated failures). Transient failures are retryable with exponential backoff and jitter; persistent failures should not be retried indefinitely.

3. Apply resilience patterns

Describe using retries with backoff, circuit breakers to prevent cascading failures, and bulkheads to isolate failures. Mention fallbacks (cached data, default values, degraded functionality) where appropriate.

4. Ensure terminal state for every request

Walk through how each request ends in success, a fallback response, or a clear error. Emphasize that no request hangs indefinitely; use deadlines and cancellation propagation.

5. Monitor and iterate

Highlight the importance of logging, metrics, and alerts for failure rates and latencies. Use this data to tune timeouts, retry policies, and circuit breaker thresholds.

Key Points to Mention

  • Timeouts and deadlines: set per-call timeouts and an overall request deadline.
  • Retries with exponential backoff and jitter, but only for idempotent operations.
  • Circuit breaker pattern to fail fast when a downstream service is unhealthy.
  • Fallback strategies: cached responses, default values, or graceful degradation.
  • Idempotency keys to ensure retries don't cause duplicate side effects.
  • Observability: structured logging, metrics (e.g., error rates, latency), and tracing to diagnose failures.

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

Q3

Design the read path for serving already-aggregated bundles at roughly 10x the write rate with p99 read latency in the tens of milliseconds.

System DesignTechnical Trade-offs
Author's notes

Easiest part of the question for me.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements: read/write ratio, data size, consistency needs, and latency SLO. Then propose a read-optimized architecture using caching, read replicas, and possibly a CDN, while ensuring the write path remains efficient. Finally, discuss trade-offs and how you would monitor and scale the solution.

Pro tip: Emphasize that you would measure and optimize for p99 latency, not just average, and that you would consider cache invalidation strategies early since they often become the bottleneck in read-heavy systems.

1. Clarify Requirements and Constraints

Ask about data volume, read/write ratio, consistency requirements, latency SLO, and budget. This ensures your design meets the actual needs.

2. Design the Read Path

Propose a multi-layer caching strategy (e.g., CDN, application cache, database cache) and read replicas to distribute load. Consider precomputed aggregates stored in a fast key-value store.

3. Address Data Consistency and Invalidation

Explain how you would keep caches fresh: TTLs, write-through, or event-driven invalidation. Discuss trade-offs between consistency and latency.

4. Ensure Scalability and Fault Tolerance

Describe how to scale horizontally (sharding, replication) and handle failures (circuit breakers, fallbacks). Mention monitoring and alerting for p99 latency.

5. Discuss Trade-offs and Alternatives

Compare options like SQL vs NoSQL, cache vs no cache, and explain why your choices are appropriate for the given constraints.

Key Points to Mention

  • Use of read replicas and caching layers (e.g., Redis, Memcached) to offload the primary database.
  • Precomputation of aggregates to avoid expensive on-the-fly calculations.
  • Cache invalidation strategies and their impact on consistency and latency.
  • Horizontal scaling via sharding and load balancing.
  • Monitoring and optimizing for p99 latency, not just average.
  • Trade-offs between consistency, availability, and latency (CAP theorem).

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

Q4

How do you guarantee exactly-once persistence of a bundle when both retries and at-least-once queue delivery can replay the same message?

System DesignData ModelingTechnical Trade-offs
Author's notes

Idempotency keys on the write operation, dedup at the database layer using the bundle's natural key (customer id or similar).

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying that exactly-once persistence is achieved through idempotent writes combined with a deduplication mechanism, not by trying to prevent message replays. Then describe a concrete design: a unique idempotency key per bundle, a durable deduplication store (e.g., database table with unique constraint), and transactional writes that atomically persist the bundle and mark the key as processed. Finally, discuss trade-offs like storage overhead, TTL for dedup records, and handling of partial failures.

Pro tip: Emphasize that exactly-once is a property of the end-to-end system, not just the queue or the consumer; you must make the persistence layer idempotent. Also mention that in financial systems like Wells Fargo, auditability and reconciliation are often more important than pure exactly-once semantics, so you might combine idempotency with a reconciliation job.

1. Clarify the problem and constraints

Acknowledge that at-least-once delivery and retries can cause duplicate messages, and exactly-once persistence means the bundle is stored exactly once despite replays. Ask about the expected scale, latency requirements, and whether the bundle has a natural unique identifier.

2. Design an idempotent write path

Propose using a unique idempotency key derived from the bundle (e.g., bundle ID + version) and a database table with a unique constraint on that key. The write operation should be an upsert or insert-if-not-exists, ensuring duplicates are ignored.

3. Implement atomic deduplication

Describe how to atomically persist the bundle and record the idempotency key in a single transaction. This prevents partial writes and ensures that if the key exists, the bundle is not persisted again.

4. Handle retries and failures

Explain that on retry, the consumer checks the dedup store first; if the key exists, it acknowledges the message without re-persisting. If the transaction fails, the message is retried, and the unique constraint prevents duplicates.

5. Discuss trade-offs and operational concerns

Mention storage overhead for dedup keys, TTL or cleanup strategies, and the need for monitoring and reconciliation. Also note that exactly-once may be relaxed to effectively-once with idempotency and at-least-once delivery.

Key Points to Mention

  • Idempotency key derived from bundle content or metadata (e.g., bundle ID + version)
  • Unique constraint or conditional write in the persistence layer (e.g., INSERT ... ON CONFLICT DO NOTHING)
  • Transactional atomicity between bundle persistence and deduplication record
  • Deduplication store with TTL or periodic cleanup to manage growth
  • Consumer-side deduplication check before processing
  • Trade-offs: storage cost, latency, and complexity vs. strict exactly-once guarantees

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

Q5

A downstream team ships a breaking schema change to one of the three APIs. How does your service detect it and contain the blast radius?

API & IntegrationsSystem DesignTechnical Trade-offs
Author's notes

Blanked for a second.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining how you would detect the breaking change through contract testing, monitoring, and alerting. Then describe a containment strategy that limits the blast radius using circuit breakers, fallbacks, and gradual rollouts. Emphasize proactive measures like versioning and consumer-driven contracts to prevent future issues.

Pro tip: Highlight the importance of consumer-driven contracts and canary deployments to catch breaking changes early and minimize impact. Mention that you would collaborate with the downstream team to establish a deprecation policy and clear communication channels.

1. Detection

Implement contract tests and runtime validation to detect schema changes. Use monitoring and alerting on error rates and latency to catch issues quickly.

2. Isolation

Isolate the affected API using circuit breakers and bulkheads to prevent failures from cascading. Route traffic away from the faulty dependency if possible.

3. Containment

Limit the blast radius by degrading gracefully with fallbacks or cached responses. Use feature flags to disable non-critical features that depend on the changed API.

4. Communication and Rollback

Alert the downstream team and coordinate a rollback or fix. If rollback isn't possible, implement a compatibility layer or adapter to handle both old and new schemas.

5. Prevention

Adopt consumer-driven contracts and versioning to prevent future breaking changes. Establish a deprecation policy and regular communication with downstream teams.

Key Points to Mention

  • Consumer-driven contracts (e.g., Pact) to catch breaking changes in CI/CD
  • Circuit breakers (e.g., Hystrix, Resilience4j) to prevent cascading failures
  • Fallback mechanisms and graceful degradation to maintain partial functionality
  • Canary deployments and feature flags to limit exposure
  • Monitoring and alerting on API error rates, latency, and schema validation failures
  • Versioning strategies (e.g., URL versioning, content negotiation) and deprecation policies

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

Q6

One downstream service has consistently high latency but is not actually failing, so your circuit breaker stays closed. How do you protect bundle latency and prevent thread pool exhaustion?

System DesignTechnical Trade-offsRoot Cause Analysis
Author's notes

Timeout per call independent of the circuit breaker state, bulkhead pattern to isolate that downstream's thread pool so it can't starve the others.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Acknowledge that a circuit breaker alone is insufficient for latency issues, then propose a multi-layered defense: timeout enforcement, bulkheads, and adaptive circuit breaking. Emphasize the need to protect the caller's thread pool and overall bundle latency by isolating slow dependencies and failing fast when latency exceeds acceptable thresholds.

Pro tip: Mention that you would instrument the downstream service's latency percentiles (p95, p99) and set timeouts based on those, not just average latency. Also, consider using a latency-aware load balancer or outlier detection to eject consistently slow instances.

1. Enforce strict timeouts

Set aggressive timeouts on calls to the downstream service, ideally slightly above the p99 latency, to prevent threads from hanging indefinitely. This ensures that even if the service is slow, calls fail fast and free up resources.

2. Implement bulkheads

Isolate the downstream service calls into a separate thread pool or semaphore with limited concurrency. This prevents one slow dependency from exhausting the entire application's thread pool and affecting other services.

3. Adopt latency-aware circuit breaking

Configure the circuit breaker to trip based on latency thresholds (e.g., percentage of slow calls) rather than just error rates. This allows the breaker to open when latency degrades, protecting the bundle.

4. Monitor and adapt

Continuously monitor latency metrics and adjust timeouts, bulkhead sizes, and circuit breaker thresholds based on observed behavior. Use outlier detection to eject slow instances from the load balancer.

5. Consider fallbacks and degradation

Design fallback mechanisms (e.g., cached responses, default values) to maintain functionality when the downstream service is slow. This ensures the bundle can still operate with degraded performance rather than failing completely.

Key Points to Mention

  • Timeout configuration based on latency percentiles (p95/p99)
  • Bulkhead pattern to isolate thread pools per dependency
  • Latency-aware circuit breaker (e.g., Resilience4j's slow call rate threshold)
  • Outlier detection and instance ejection in load balancing
  • Fallback strategies and graceful degradation
  • Monitoring and alerting on latency metrics to proactively detect issues

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

Q7

After a multi-hour downstream outage, how do you safely replay the DLQ without overwhelming the now-recovered service?

System DesignAPI & IntegrationsCross-functional Alignment
Author's notes

Rate-limited replay with exponential ramp-up, not a full blast of everything at once.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by emphasizing safety and control: assess the DLQ volume, then replay in a throttled, batched manner with monitoring and the ability to pause or roll back. Highlight the importance of coordination with downstream teams and validating service health before and during replay.

Pro tip: Use a canary approach: replay a small batch first, verify end-to-end processing and latency, then gradually increase rate while watching error budgets. This demonstrates risk-aware engineering and aligns with Wells Fargo's emphasis on stability and compliance.

1. Assess and Prepare

Quantify the DLQ backlog, categorize messages by type/priority, and verify the downstream service's health and capacity. Ensure you have a rollback plan and necessary approvals.

2. Design a Controlled Replay Strategy

Choose a replay mechanism (e.g., custom tool, Kafka consumer, or cloud-native DLQ redrive) that supports rate limiting, batching, and idempotency. Define target throughput based on service SLAs.

3. Implement Throttling and Monitoring

Start with a low replay rate (e.g., 10% of normal traffic), monitor key metrics (latency, error rates, queue depth), and gradually increase while staying within safe thresholds. Set up alerts for anomalies.

4. Execute and Validate

Run the replay in batches, validating message processing and end-to-end outcomes. Pause immediately if issues arise, and communicate progress to stakeholders.

5. Post-Replay Review

After completion, verify DLQ is empty, document lessons learned, and update runbooks or automation to prevent future outages and improve replay procedures.

Key Points to Mention

  • Idempotency: ensure replayed messages don't cause duplicate side effects.
  • Rate limiting and backpressure: use token buckets, circuit breakers, or queue-based flow control.
  • Monitoring and observability: track latency, error rates, and throughput in real-time.
  • Coordination with downstream teams: align on maintenance windows and capacity.
  • Rollback and pause capability: ability to stop replay instantly if problems occur.
  • Compliance and audit: maintain logs of replay actions for regulatory requirements.

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