← Coinbase Interview Insights

Coinbase·Software Engineer·Technical Phone Screen·Senior

Senior
May 2026

Summary

Coinbase backend interview focused on extending a key-value store with TTL support. The design space was broader than I expected and the discussion went pretty deep into trade-offs I hadn't fully thought through beforehand.

Questions Asked (3)

Q1

You're given an in-memory key-value store with store, read, and scan operations. Extend it to support per-key TTL, where reads and scans ignore or remove expired keys. Walk through your design.

System DesignTechnical Trade-offsAPI & Integrations
Author's notes

I jumped straight to lazy expiration because it felt obvious.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then propose a design that augments the existing key-value store with expiration metadata. Discuss trade-offs between lazy and active expiration, and how to handle scans efficiently while ensuring expired keys are ignored or removed.

Pro tip: Mention that Coinbase likely values low-latency reads and high throughput, so consider the impact of expiration on read performance and propose a design that minimizes overhead, such as lazy expiration with periodic cleanup.

1. Clarify Requirements

Ask about expected scale, read/write patterns, TTL granularity, and whether expired keys should be removed immediately or lazily. Confirm if scans need to be consistent or can tolerate some staleness.

2. Design Data Model

Propose storing each key with its value and an expiration timestamp (e.g., a wrapper object or separate expiration map). Discuss memory overhead and potential optimizations like using a min-heap for expiration tracking.

3. Implement Read and Scan Logic

For reads, check expiration before returning; if expired, treat as missing and optionally delete. For scans, iterate over keys, skip expired ones, and optionally remove them. Consider using a background thread for proactive cleanup.

4. Handle Expiration Strategies

Compare lazy expiration (on access) vs. active expiration (background sweeper). Discuss trade-offs: lazy is simpler but may leave expired keys consuming memory; active reduces memory but adds complexity and potential contention.

5. Address Concurrency and Performance

Ensure thread-safety for concurrent reads/writes and expiration. Consider lock granularity, use of read-write locks, and how expiration checks impact latency. Discuss potential optimizations like approximate expiration or time-wheel.

Key Points to Mention

  • Trade-offs between lazy and active expiration, including memory usage and CPU overhead.
  • Impact on scan performance: how to avoid scanning expired keys efficiently, possibly using sorted structures.
  • Concurrency control: ensuring thread-safety without introducing bottlenecks.
  • Memory management: strategies to reclaim memory from expired keys, such as periodic sweeps or reference counting.
  • API design: whether to expose TTL in store/read/scan operations and how to handle updates to TTL.
  • Edge cases: keys with no TTL, TTL updates, and clock skew considerations.

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

Q2

Compare lazy expiration on access versus a background sweeper thread for purging expired keys. What are the memory and latency trade-offs?

Technical Trade-offsSystem Design
Author's notes

This part I actually felt decent about.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining both strategies clearly: lazy expiration checks keys on access, while a background sweeper proactively scans and removes expired keys. Then compare their trade-offs in terms of memory usage (stale keys lingering) and latency (access-time overhead vs. periodic CPU spikes), and conclude with when to use each or a hybrid approach.

Pro tip: Mention that real systems like Redis use a hybrid approach: lazy expiration on access plus periodic random sampling to bound memory, which balances latency and memory efficiently.

1. Define the strategies

Briefly explain lazy expiration (check on access) and background sweeper (periodic scan) to ensure a common understanding.

2. Analyze memory trade-offs

Discuss how lazy expiration can lead to memory bloat from expired keys not being purged until accessed, while a sweeper proactively frees memory but may consume CPU.

3. Analyze latency trade-offs

Explain that lazy expiration adds latency to read/write operations due to expiration checks, whereas a sweeper can cause periodic latency spikes if not tuned properly.

4. Consider system constraints

Factor in workload patterns (read-heavy vs. write-heavy), memory limits, and latency sensitivity to determine which approach suits better.

5. Propose a hybrid solution

Suggest combining both: lazy expiration for immediate correctness and a background sweeper for memory reclamation, as done in production systems like Redis.

Key Points to Mention

  • Lazy expiration avoids background CPU usage but may cause memory bloat if keys are rarely accessed.
  • Background sweeper bounds memory usage but can introduce latency spikes and CPU overhead during scans.
  • Hybrid approach: lazy expiration on access plus periodic random sampling (e.g., Redis's active expiration).
  • Trade-off depends on workload: read-heavy vs. write-heavy, memory constraints, and latency SLAs.
  • Consider using time-to-live (TTL) and eviction policies to manage memory proactively.
  • Mention that in distributed systems, a sweeper must be coordinated to avoid duplicate work or missed keys.

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

Q3

Where would you store the expiry timestamp for each key, and why? Inline with the value, or in a separate structure like a min-heap keyed by expiry time?

Data ModelingAlgorithms & Data Structures
Author's notes

Went with inline first since it's the path of least resistance.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: are we optimizing for memory, read/write latency, or simplicity? Then compare storing expiry inline with the value versus a separate min-heap, discussing trade-offs in time complexity, memory overhead, and concurrency. Finally, recommend a hybrid or context-specific solution, explaining why it fits the scenario.

Pro tip: Mention that a min-heap alone doesn't support efficient deletion or update of arbitrary keys, so you'd typically pair it with a hash map for O(1) access, or use a timing wheel for high-throughput systems. This shows you understand real-world implementation details beyond textbook data structures.

1. Clarify requirements and constraints

Ask about expected read/write patterns, memory constraints, and whether expired keys must be removed promptly or lazily. This determines the appropriate data structure.

2. Evaluate inline storage

Storing expiry with the value is simple, memory-efficient for small values, and allows O(1) expiry checks on read. However, active expiration requires scanning all keys, which is inefficient.

3. Evaluate separate min-heap

A min-heap keyed by expiry enables O(log n) insertion and O(1) access to the earliest expiring key, making active expiration efficient. But it adds memory overhead and requires a mapping from heap entries to keys for updates/deletions.

4. Consider hybrid and advanced structures

Combine a hash map for key-value-expiry storage with a min-heap for expiration ordering, or use a timing wheel for high-throughput scenarios. Discuss trade-offs in complexity and performance.

5. Recommend based on context

For simple caches with lazy expiration, inline is sufficient. For systems needing precise, timely expiration (e.g., rate limiting, sessions), a separate min-heap or timing wheel is better. Justify your choice with the requirements from step 1.

Key Points to Mention

  • Time complexity of operations: inline gives O(1) read but O(n) active expiration; min-heap gives O(log n) insert and O(1) min access.
  • Memory overhead: inline stores timestamp per key; min-heap adds pointers and heap structure overhead.
  • Concurrency and locking: separate structures may require more complex synchronization.
  • Lazy vs. active expiration: inline supports lazy expiration naturally; min-heap enables efficient active expiration.
  • Need for auxiliary hash map to support deletion/update in min-heap.
  • Alternative: timing wheel for high-resolution, high-throughput expiration.

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