← Stripe Interview Insights

Stripe·Software Engineer·Technical Phone Screen·Senior

Senior
Jul 2026

Summary

Stripe coding round for a software engineer role. The whole thing was one big multi-part design-and-implement question about a connection router, built up incrementally across five parts. Took longer than I expected to get all the edge cases right.

Questions Asked (5)

Q1

Design and implement a stateful connection router for a multi-tenant server system. Start with basic round-robin routing: given N target servers, implement a connect(connId) method that assigns each new connection to the next available target in cyclic order and returns the chosen target index.

Algorithms & Data StructuresSystem Design
Author's notes

The round-robin part itself is not bad, just a pointer you increment mod N.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then design a simple round-robin router using an atomic counter to ensure thread safety. Implement the connect method to return the next target index in cyclic order, and discuss how to extend it to a stateful, multi-tenant system with per-tenant routing state.

Pro tip: Mention that round-robin is just the starting point; in production, you'd likely need health checks, weighted routing, and sticky sessions for stateful connections. Also, highlight the importance of thread safety in a multi-tenant environment.

1. Clarify Requirements

Ask about the number of tenants, expected connection rate, thread safety needs, and whether connections are long-lived or short-lived. Confirm that the initial implementation should be basic round-robin.

2. Design Data Structures

Use an atomic integer counter to track the next target index, ensuring thread-safe increments. For multi-tenancy, consider a map from tenant ID to their own router state.

3. Implement connect Method

In connect(connId), atomically increment the counter modulo N to get the target index. Return the index. Ensure the counter wraps around correctly.

4. Discuss Extensibility

Explain how to extend to weighted round-robin, health checks, or consistent hashing for stateful connections. Mention that stateful routing may require tracking connection-to-target mappings.

5. Analyze Complexity and Trade-offs

State that time complexity is O(1) per connection, and space is O(1) for basic round-robin. Discuss trade-offs like fairness vs. load distribution and the impact of thread contention.

Key Points to Mention

  • Thread safety: use atomic operations or locks to handle concurrent connect calls.
  • Multi-tenancy: isolate routing state per tenant to avoid interference.
  • Cyclic order: use modulo arithmetic to wrap around the target list.
  • Statefulness: maintain connection-to-target mapping if connections are long-lived.
  • Extensibility: plan for health checks, weighted routing, and failover.
  • Complexity: O(1) time and space for basic round-robin.

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

Q2

Extend connect(connId) to handle duplicate connection requests: if the same connId is already connected, return its existing target without modifying any state.

Algorithms & Data StructuresSystem Design
Author's notes

Straightforward once you have the hashmap.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the existing data structures and invariants of the connect function, then propose a simple early-return check that leverages the existing lookup mechanism. Emphasize that the solution must be idempotent and thread-safe if applicable, and discuss how to verify the target is returned without side effects.

Pro tip: Mention that duplicate connection requests are common in distributed systems and that idempotency is key to avoiding race conditions and resource leaks. Also, suggest adding logging or metrics to track duplicate attempts for observability.

1. Clarify requirements and constraints

Ask about the expected behavior: should it return the existing target silently, or log a warning? Are there concurrency concerns? What is the data structure used to track connections?

2. Identify the lookup mechanism

Determine how to check if connId is already connected. This likely involves a map or dictionary from connId to target. Ensure the lookup is O(1) and does not mutate state.

3. Implement early return

At the beginning of connect, check if connId exists in the connection registry. If so, return the existing target immediately, bypassing any state changes.

4. Handle concurrency (if needed)

If the system is multithreaded, use appropriate locking or atomic operations to ensure the check-and-return is atomic, preventing race conditions.

5. Test and validate

Write unit tests for duplicate connection requests, verifying that the target is returned and no side effects occur (e.g., no new connections, no counter increments).

Key Points to Mention

  • Idempotency: duplicate requests should not change system state.
  • Data structure: use a hash map for O(1) lookup of existing connections.
  • Concurrency: ensure thread-safety with locks or atomic operations if needed.
  • Side effects: avoid incrementing counters, creating new resources, or logging errors.
  • Return value: return the existing target exactly as stored.
  • Observability: consider logging or metrics for duplicate attempts to aid debugging.

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

Q3

Implement a disconnect(connId) method that removes an active connection, decrements the target's connection count, and returns true. If the connId isn't found, return false without changing any state.

Algorithms & Data StructuresSystem Design
Author's notes

Pretty clean to implement.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the data structures and requirements: how connections are stored, what 'target' means, and whether thread safety is needed. Then outline an algorithm that looks up the connection, updates the target's count, removes the connection, and returns true; otherwise returns false. Finally, discuss edge cases, complexity, and potential concurrency issues.

Pro tip: Mention that you would use a hash map for O(1) lookup and removal, and emphasize the importance of atomicity in concurrent environments—this shows you think about real-world reliability, which Stripe values.

1. Clarify requirements and assumptions

Ask questions to understand the data model: how connections are stored, what 'target' refers to, and whether the method must be thread-safe. Confirm the expected return values and side effects.

2. Design the data structures

Propose using a hash map (or similar) to store connections by connId for O(1) lookup, and a way to track each target's connection count (e.g., a counter per target).

3. Outline the algorithm

Describe the steps: look up connId; if not found, return false; otherwise, retrieve the associated target, decrement its connection count, remove the connection from the map, and return true.

4. Address edge cases and concurrency

Discuss handling of invalid connId, ensuring no state change on failure, and if needed, using locks or atomic operations to prevent race conditions.

5. Analyze complexity and test

State time and space complexity (O(1) for hash map operations), and suggest test cases: existing connId, non-existing connId, concurrent disconnects, and count reaching zero.

Key Points to Mention

  • Use a hash map for O(1) lookup and removal of connections.
  • Maintain a separate counter per target to track active connections.
  • Ensure atomicity: if connId not found, return false without modifying state.
  • Consider thread safety: use locks or concurrent data structures if multiple threads may call disconnect.
  • Handle edge cases: null/empty connId, target with zero connections, and idempotency.
  • Discuss time and space complexity: O(1) time, O(n) space for n connections.

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

Q4

Enforce per-target capacity limits in the connect logic. During round-robin scanning, skip targets that are full. If every available target is at capacity, return -1 and leave all state unchanged.

Algorithms & Data StructuresSystem DesignTechnical Trade-offs
Author's notes

This is where the round-robin scan gets a little more involved.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the data structures and constraints, then outline an algorithm that scans targets in round-robin order while skipping full ones. Emphasize that if all targets are full, return -1 without mutating any state, and discuss how to achieve this efficiently.

Pro tip: Mention that you would track the number of full targets to avoid infinite loops and enable early termination, and that you would use a two-phase approach: first check if any capacity is available, then perform the assignment only if possible.

1. Clarify requirements and constraints

Ask about the data structure for targets, how capacity is tracked, and whether the round-robin pointer should be updated on failure. Confirm that state must remain unchanged if no target is available.

2. Design the algorithm

Propose scanning targets in round-robin order, skipping those at capacity. Keep a count of full targets or limit iterations to the number of targets to detect when all are full.

3. Handle the all-full case

If no target is found after scanning all, return -1 and ensure no state (e.g., round-robin index) is modified. Discuss how to achieve this by deferring state updates until a target is selected.

4. Analyze complexity and trade-offs

Explain time complexity (O(n) worst case) and space complexity (O(1) extra). Discuss alternatives like maintaining a separate list of available targets for O(1) selection, and their trade-offs.

5. Test with edge cases

Walk through scenarios: all targets full, some full, single target, and wrap-around in round-robin. Verify that state remains unchanged on failure.

Key Points to Mention

  • Round-robin scanning with a pointer that wraps around
  • Skipping targets at capacity without modifying their state
  • Detecting when all targets are full (e.g., by counting or limiting iterations)
  • Returning -1 and leaving all state unchanged (no side effects)
  • Time and space complexity analysis
  • Potential optimizations like maintaining a list of available targets

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

Q5

Implement a shutdown(targetIndex) method that marks a target as permanently unavailable, evicts all its current connections, and returns the evicted connIds in the order those connections were originally created.

System DesignAlgorithms & Data StructuresTechnical Trade-offs
Author's notes

The ordering requirement is what makes this interesting.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Clarify the data model and requirements, then design a data structure that supports efficient shutdown and ordered eviction. Discuss trade-offs between different approaches (e.g., linked list vs. tree) and handle edge cases like duplicate shutdowns or invalid indices.

Pro tip: Mention that you would maintain a doubly linked list of connections per target to preserve creation order, and a hash map for O(1) access to connections. This shows you understand the importance of both time complexity and order preservation.

1. Clarify requirements and constraints

Ask about the expected scale (number of targets, connections), concurrency requirements, and whether the order is based on creation timestamp or insertion sequence. Confirm that shutdown should be idempotent and that the target remains unavailable.

2. Design the data structures

Propose maintaining a mapping from targetIndex to a list of connections (e.g., a doubly linked list) that preserves creation order, and a global map from connId to connection details for quick lookup. Consider using a balanced BST or skip list if connections are frequently added/removed.

3. Implement shutdown logic

On shutdown, mark the target as unavailable (e.g., set a flag or remove from active targets), then iterate through its connections in order, collect their connIds, and remove them from all relevant structures. Return the collected list.

4. Analyze complexity and trade-offs

Discuss time complexity: O(k) where k is the number of connections for that target, and space complexity. Compare alternatives like using a min-heap ordered by creation time, which would be O(k log k) but simpler if connections are not stored per target.

5. Handle edge cases and concurrency

Address cases: targetIndex out of bounds, target already shut down, no connections. If concurrent, suggest locking per target or using concurrent data structures to avoid race conditions.

Key Points to Mention

  • Order preservation: use a data structure that maintains insertion order, such as a doubly linked list or an ordered map.
  • Efficiency: aim for O(1) access to target's connections and O(k) eviction, where k is the number of connections.
  • Idempotency: ensure shutdown can be called multiple times without error, returning an empty list on subsequent calls.
  • Memory management: remove references to evicted connections to allow garbage collection.
  • Concurrency: if multiple threads can call shutdown or add connections, use appropriate synchronization (e.g., per-target locks).
  • Trade-offs: discuss alternative designs like using a global ordered list with target filtering, which might be simpler but less efficient.

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