← Coinbase Interview Insights

Coinbase·Software Engineer·Online Assessment (OA)·Intermediate

Intermediate
Jul 2026

Summary

Coinbase SWE online assessment, the whole thing was a single evolving in-memory database problem split into four parts. Each part built on the last so you couldn't really skip ahead or ignore earlier code. Pretty classic OA format but the TTL and backup/restore parts had enough edge cases to keep you on your toes.

Questions Asked (4)

Q1

Implement a basic in-memory key-value store with put and get operations, where each record has a string key, string value, and integer timestamp. Multiple writes to the same key should return the most recent value.

Algorithms & Data StructuresSystem Design
Author's notes

Straightforward enough.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements (e.g., timestamp handling, concurrency, persistence) and then propose a design using a hash map for O(1) average-time put/get. Discuss how to handle multiple writes with timestamps, such as storing the latest value per key or maintaining versioned entries, and consider edge cases like out-of-order timestamps.

Pro tip: Mention that in a real system like Coinbase, you'd likely need to handle concurrent access and persistence, so briefly touch on thread-safety (e.g., using locks or concurrent data structures) and durability options (e.g., write-ahead log) to show production awareness.

1. Clarify Requirements

Ask about expected operations, timestamp semantics (e.g., should get return the value with the highest timestamp or the latest write?), concurrency needs, and memory constraints.

2. Choose Data Structures

Propose using a hash map (dictionary) to store key-value pairs, where each value includes the string value and timestamp. For handling multiple writes, either overwrite if the new timestamp is greater, or store a list of versions per key.

3. Define Operations

Implement put(key, value, timestamp) to update the store, ensuring the most recent timestamp wins. Implement get(key) to return the value associated with the highest timestamp for that key.

4. Handle Edge Cases

Consider out-of-order timestamps, duplicate timestamps, missing keys, and concurrency. Decide on behavior (e.g., ignore older timestamps, return null for missing keys).

5. Analyze Complexity and Trade-offs

Discuss time and space complexity (O(1) average for put/get with hash map, O(n) worst-case for versioned lists). Mention potential improvements like using a balanced BST for ordered timestamps if range queries are needed.

Key Points to Mention

  • Use a hash map for O(1) average-time put and get operations.
  • Store the timestamp with each value to determine the most recent write.
  • Handle out-of-order timestamps by comparing timestamps and only updating if the new timestamp is greater.
  • Consider thread-safety for concurrent access, e.g., using locks or ConcurrentHashMap.
  • Discuss persistence options like write-ahead logging for durability.
  • Analyze trade-offs between simplicity and scalability, e.g., versioned storage vs. overwriting.

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

Q2

Extend the database to support a scan operation that returns all key-value pairs whose keys share a given prefix, sorted lexicographically.

Algorithms & Data StructuresSystem Design
Author's notes

Easy to get wrong if you're not careful about the sort.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements (e.g., expected scale, read/write patterns, consistency needs) and then propose a data structure that supports efficient prefix scans, such as a trie or a sorted index (e.g., LSM-tree with SSTables). Discuss how to implement the scan operation, including lexicographic ordering, and address trade-offs like memory usage, latency, and concurrency.

Pro tip: Mention that many production databases (e.g., LevelDB, RocksDB) use a sorted string table (SSTable) with a block index to support efficient prefix scans, and highlight the importance of considering range scans in the context of the underlying storage engine.

1. Clarify Requirements

Ask about the expected data size, read/write ratio, latency requirements, and whether the scan needs to be consistent or can be eventually consistent. This shapes the design.

2. Choose Data Structure

Propose a trie, a sorted array with binary search, or an LSM-tree with SSTables. Explain how each supports prefix scans and lexicographic ordering.

3. Design Scan Algorithm

Describe how to traverse the data structure to find all keys with the given prefix, ensuring they are returned in sorted order. For a trie, do a DFS from the prefix node; for SSTables, seek to the prefix and iterate.

4. Address Scalability and Performance

Discuss how the design handles large datasets, concurrency, and persistence. Mention indexing, caching, and partitioning strategies if needed.

5. Evaluate Trade-offs

Compare alternatives (e.g., trie vs. sorted index) in terms of memory, speed, and complexity. Explain why your chosen approach is suitable for the given context.

Key Points to Mention

  • Trie data structure and its ability to efficiently retrieve all keys with a given prefix
  • Lexicographic ordering: ensuring keys are sorted, possibly using a sorted index or in-order traversal
  • LSM-tree and SSTables as used in production databases (e.g., LevelDB, RocksDB) for range scans
  • Time complexity: O(k + m) where k is prefix length and m is number of matching keys, or O(log n + m) for sorted arrays
  • Space-time trade-offs: tries can be memory-heavy but fast; sorted arrays are compact but slower for inserts
  • Concurrency and consistency: how to handle concurrent writes during a scan (e.g., snapshots, MVCC)

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

Q3

Add optional TTL support to the put operation so entries expire after a given number of seconds. Get and scan should not return expired entries.

System DesignTechnical Trade-offs
Author's notes

This is where I slowed down.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: TTL is optional per put, expiration is lazy or active, and get/scan must filter expired entries. Then propose a design that stores an expiration timestamp alongside each value, and discuss trade-offs between lazy deletion (on read) and active deletion (background sweeper). Finally, address edge cases like clock skew, TTL updates, and scan efficiency.

Pro tip: Mention that lazy expiration alone can cause memory bloat, so a hybrid approach with periodic cleanup is often best—this shows you think about production concerns beyond just correctness.

1. Clarify requirements and constraints

Ask whether TTL is per-key or per-put, if updates reset TTL, and whether expired entries should be removed immediately or lazily. Also confirm if scan needs to be efficient for large datasets.

2. Design data model

Store each entry as a value plus an optional expiration timestamp (e.g., Unix epoch seconds). If TTL is not provided, expiration is null (never expires).

3. Implement expiration logic

On get and scan, check if the entry's expiration timestamp is in the past; if so, treat it as absent and optionally delete it. For active cleanup, use a background thread that periodically scans and removes expired entries.

4. Handle scan efficiently

For scan, iterate over entries and skip expired ones. If the data store supports range queries, consider indexing by expiration time to quickly find and purge expired entries.

5. Discuss trade-offs and edge cases

Compare lazy vs. active expiration: lazy saves CPU but may return stale data if not checked; active uses more resources but keeps memory clean. Address clock skew, TTL updates, and concurrency.

Key Points to Mention

  • Lazy vs. active expiration and their trade-offs (memory vs. CPU, consistency)
  • Storing expiration timestamp with each entry and checking on read
  • Handling scan by filtering expired entries and potential performance impact
  • Edge cases: TTL update on put, clock skew, and concurrent access
  • Memory management: preventing unbounded growth from expired entries
  • Optional TTL: default behavior when TTL is not provided

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

Q4

Add backup and restore functionality. Backup should capture all non-expired entries at a given timestamp and return an ID. Restore should bring the database back to that snapshot, with TTLs adjusted so remaining lifetime is preserved relative to the restore time.

System DesignData ModelingTechnical Trade-offs
Author's notes

The TTL-on-restore behavior is the nastiest part of this whole problem.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then outline a high-level design for backup and restore, focusing on data modeling and TTL handling. Dive into technical details like snapshot isolation, ID generation, and TTL adjustment, and discuss trade-offs (e.g., storage overhead, consistency). Conclude with potential optimizations and edge cases.

Pro tip: Emphasize the importance of atomicity and consistency during backup and restore, and propose using a copy-on-write or versioning mechanism to avoid blocking writes. Also, discuss how to handle concurrent modifications during restore to ensure a consistent snapshot.

1. Clarify Requirements and Constraints

Ask questions to understand the scale, consistency requirements, and expected backup frequency. Clarify whether backups should be incremental or full, and how restore should handle concurrent writes.

2. Design Backup Mechanism

Propose a method to capture all non-expired entries at a given timestamp, such as iterating over the keyspace or using a snapshot isolation technique. Generate a unique backup ID and store metadata (timestamp, ID) for later retrieval.

3. Design Restore Mechanism

Outline how to restore the database to the snapshot, ensuring that TTLs are adjusted to preserve remaining lifetime relative to restore time. Discuss how to handle entries that expired between backup and restore.

4. Address TTL Adjustment

Explain the calculation: for each entry, compute remaining TTL at backup time (original TTL minus elapsed time since entry creation). During restore, set new TTL as remaining TTL plus time elapsed since backup, or simply remaining TTL if restore time is considered as new 'now'.

5. Discuss Trade-offs and Optimizations

Compare approaches (e.g., full vs. incremental backup, in-memory vs. persistent storage). Discuss trade-offs in terms of performance, storage, and consistency. Suggest optimizations like lazy deletion or background cleanup.

Key Points to Mention

  • Snapshot isolation and consistency during backup
  • Unique backup ID generation and metadata storage
  • TTL adjustment formula: new TTL = remaining TTL at backup + (restore time - backup time)
  • Handling expired entries during backup and restore
  • Concurrency control during restore (e.g., blocking writes or using versioning)
  • Storage and performance trade-offs (e.g., full vs. incremental backups)

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