← Etsy Interview Insights

Etsy·Data Scientist·Onsite - System Design / Architecture·Senior

SeniorPrefer not to say
Jul 2026Remote

Summary

System design round at Etsy for a Data Scientist role, focused entirely on building an autocomplete service from scratch. Pretty deep dive, lots of follow-ups on tradeoffs I wasn't fully prepared for.

Questions Asked (7)

Q1

Design an autocomplete service that handles up to 5 million UTF-8 words with popularity scores, returns the top 5 prefix-matched suggestions after each keystroke, supports ~1,000 inserts/deletes per second, and meets sub-20ms p99 latency at 5,000 QPS within 300MB of memory.

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

This was the main question and it ate the whole session.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then propose a trie-based solution with top-K caching at each node to meet latency and memory targets. Discuss how to handle updates efficiently and how to shard the service for scalability, while addressing UTF-8 encoding and memory optimization.

Pro tip: Emphasize the trade-off between memory and latency: storing top-K suggestions at each node speeds up queries but increases memory; use compression and pruning to stay within 300MB. Also, mention that popularity scores can be updated asynchronously to avoid blocking reads.

1. Clarify Requirements and Constraints

Confirm the scale (5M words, 5K QPS, 1K updates/sec, sub-20ms p99, 300MB), the definition of 'popularity score', and whether suggestions should be personalized or global.

2. Choose Data Structure and Algorithm

Propose a trie (prefix tree) where each node stores the top 5 suggestions for its prefix, sorted by popularity. Discuss UTF-8 handling and memory-efficient node representation.

3. Address Memory and Latency Optimization

Explain how to fit within 300MB: use compact trie nodes, store only top-K per node, compress common prefixes, and possibly use a probabilistic data structure for pruning. For latency, ensure O(prefix length) lookup and cache hot prefixes.

4. Handle Updates and Scalability

Describe how to process 1K inserts/deletes per second: batch updates, use a write-ahead log, and update trie nodes asynchronously. For 5K QPS, shard the trie by prefix range and replicate for read scalability.

5. Discuss Trade-offs and Alternatives

Compare trie with other approaches (e.g., inverted index, n-gram models) and justify choices. Mention potential bottlenecks and how to monitor and adjust.

Key Points to Mention

  • Trie data structure with top-K suggestions stored at each node
  • Memory optimization techniques: compact node representation, prefix compression, pruning low-popularity branches
  • Latency optimization: O(prefix length) lookup, caching, and asynchronous updates
  • Sharding and replication for scalability to 5K QPS and 1K updates/sec
  • UTF-8 encoding considerations and normalization (e.g., case folding, Unicode normalization)
  • Trade-offs between memory usage and query speed, and between consistency and availability for updates

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

Q2

Which data structure would you choose for this autocomplete system and why, comparing options like compressed tries, ternary search trees, DAWGs, or sorted arrays with binary search?

Algorithms & Data StructuresTechnical Trade-offsSystem Design
Author's notes

I went with compressed trie and gave a reasonable argument around shared prefix storage, but I fumbled the DAWG comparison.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements of the autocomplete system (e.g., dataset size, update frequency, latency constraints) and then compare the data structures based on those criteria. Recommend a primary choice with justification, and mention alternatives with trade-offs, showing awareness of practical implementation at Etsy's scale.

Pro tip: Emphasize that the choice depends on the specific use case—e.g., if the system is read-heavy and static, a DAWG or compressed trie is optimal; if updates are frequent, a ternary search tree might be better. Also, mention that hybrid approaches (e.g., trie + caching) are common in production.

1. Clarify Requirements

Ask about the expected scale (number of queries, vocabulary size), update frequency, latency requirements, and memory constraints. This shows you understand that the optimal data structure depends on the context.

2. Compare Data Structures

Briefly describe each option: compressed trie (space-efficient, fast prefix search), ternary search tree (balanced, good for dynamic updates), DAWG (minimal space, but complex to build/update), sorted array + binary search (simple, but slow updates and memory-heavy).

3. Evaluate Trade-offs

Discuss time complexity for prefix search, insertion, deletion, and memory usage. For example, tries offer O(k) search (k = prefix length), while sorted arrays offer O(log n) but require O(n) updates.

4. Make a Recommendation

Choose a data structure based on the clarified requirements. For Etsy, where search queries might be relatively static and read-heavy, a DAWG or compressed trie could be ideal; if real-time updates are needed, a ternary search tree might be better.

5. Mention Practical Considerations

Bring up implementation details like caching top suggestions, using a hybrid approach (e.g., trie for prefixes + hash map for exact matches), and handling Unicode or case sensitivity.

Key Points to Mention

  • Time complexity of prefix search: O(k) for tries vs O(log n) for sorted arrays
  • Memory efficiency: DAWG and compressed trie reduce redundancy, while sorted arrays store full strings
  • Update performance: ternary search trees and tries allow dynamic insertions; DAWGs and sorted arrays are costly to update
  • Implementation complexity: DAWGs are complex to build and update, while sorted arrays are simple but less scalable
  • Real-world usage: many production autocomplete systems use tries or DAWGs with caching layers
  • Hybrid approaches: combining a trie with a hash map or caching frequent queries

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

Q3

How would you maintain a top-5 list per prefix without blowing up memory, for example using small heaps, shared postings lists, or lazy enumeration?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This is where I actually felt okay.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem constraints (e.g., number of prefixes, memory budget, update frequency) and then propose a memory-efficient solution that combines small heaps for top-5 tracking with shared postings lists for prefix storage and lazy enumeration for on-demand processing. Emphasize trade-offs between memory, latency, and accuracy, and discuss how to handle updates and queries efficiently.

Pro tip: Mention that you would use a min-heap of size 5 per prefix to keep only the top items, and share postings lists across prefixes to avoid duplication, but also consider approximate methods like count-min sketch if exact counts are not required.

1. Clarify requirements and constraints

Ask about the scale (number of prefixes, items per prefix), memory limits, update frequency, and whether exact top-5 is required. This shows you understand the problem before diving into solutions.

2. Propose a memory-efficient data structure

Suggest using a min-heap of size 5 per prefix to maintain the top-5 items, which uses O(5) memory per prefix. For storing the items, consider shared postings lists (e.g., inverted index) to avoid duplicating data across prefixes.

3. Explain lazy enumeration and updates

Describe how to lazily enumerate items for a prefix by traversing the shared postings list and updating the heap only when necessary. Discuss how to handle updates (e.g., new items) by checking if they belong in the top-5 and updating the heap accordingly.

4. Discuss trade-offs and alternatives

Compare with alternative approaches like storing full sorted lists (memory-heavy) or using approximate algorithms (e.g., count-min sketch) for memory savings at the cost of accuracy. Highlight the balance between memory, speed, and exactness.

5. Summarize and conclude

Recap the proposed solution, emphasizing how it meets the memory constraints while maintaining performance, and mention any potential optimizations or edge cases (e.g., handling ties, dynamic prefixes).

Key Points to Mention

  • Min-heap of size 5 per prefix to track top items with O(1) update time and minimal memory.
  • Shared postings lists (inverted index) to store item-prefix relationships without duplication.
  • Lazy enumeration to process items on-demand, reducing memory footprint.
  • Trade-offs: exact vs approximate (e.g., count-min sketch), memory vs latency.
  • Handling updates: incremental heap updates and potential need for periodic recomputation.
  • Scalability: partitioning prefixes or using distributed processing if data is too large.

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

Q4

How do you handle dynamic updates (inserts and deletes at ~1,000 per second) while supporting concurrent reads with correctness guarantees?

System DesignTechnical Trade-offs
Author's notes

Talked about copy-on-write and read-write locks.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: data volume, read/write patterns, latency and consistency needs. Then propose a system design that separates read and write paths, using a write-optimized store (e.g., LSM-tree based) with a read-optimized cache or materialized view, and discuss trade-offs between consistency models (e.g., eventual vs. strong) and how to achieve correctness (e.g., via versioning or transactions).

Pro tip: Emphasize that at 1,000 writes/sec, the bottleneck is often not the database but the coordination and indexing; consider using a distributed log (e.g., Kafka) to buffer writes and enable asynchronous, idempotent processing for scalability and fault tolerance.

1. Clarify Requirements

Ask about data size, read/write ratio, latency SLAs, and consistency requirements (e.g., strong vs. eventual). This ensures the design meets actual needs.

2. Choose Data Store & Architecture

Select a write-optimized database (e.g., Cassandra, HBase) for high ingest and a read-optimized layer (e.g., Redis, Elasticsearch) for fast queries. Consider a lambda architecture with batch and speed layers.

3. Handle Concurrency & Correctness

Use techniques like MVCC, optimistic concurrency control, or distributed transactions to ensure correctness. Discuss isolation levels and how to handle conflicts.

4. Address Trade-offs

Explain trade-offs: e.g., eventual consistency improves availability but may return stale data; strong consistency may increase latency. Propose a hybrid approach if needed.

5. Monitor & Scale

Mention monitoring for hotspots, backpressure, and auto-scaling. Discuss partitioning/sharding to distribute load and ensure scalability.

Key Points to Mention

  • LSM-tree vs. B-tree storage engines and their write/read performance characteristics
  • Use of write-ahead logging (WAL) and memtables for durability and fast writes
  • Consistency models: eventual, strong, causal, and their impact on correctness
  • Concurrency control mechanisms: MVCC, 2PL, optimistic vs. pessimistic locking
  • Caching strategies (e.g., write-through, write-behind) and cache invalidation
  • Partitioning/sharding and replication for scalability and fault tolerance

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

Q5

If fewer than 5 exact prefix matches exist, how would you backfill suggestions using edit-distance-1 candidates efficiently?

Algorithms & Data StructuresSystem Design
Author's notes

Honestly the part I was least prepared for.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the constraints: the prefix index is already built, and we need to efficiently generate edit-distance-1 candidates only when exact prefix matches are insufficient. Then describe a two-phase approach: first, generate all possible edit-distance-1 strings from the query (deletions, substitutions, insertions, transpositions) and look them up in a hash-based dictionary or trie; second, rank and merge these candidates with any existing prefix matches, ensuring low latency and relevance.

Pro tip: Emphasize that edit-distance-1 generation is cheap (O(26 * L) for substitutions, O(L) for deletions/transpositions) and can be precomputed or cached, but the real challenge is ranking and deduplication—so mention how you'd use a priority queue or score-based merge to keep the top suggestions.

1. Clarify requirements and constraints

Confirm the definition of 'exact prefix match', the expected latency, and whether the suggestion list must be ranked. Ask if the edit-distance-1 candidates should be restricted to valid dictionary words or any string.

2. Generate edit-distance-1 candidates

For the query string, systematically generate all strings within edit distance 1: deletions (remove each character), substitutions (replace each character with 25 others), insertions (insert each letter at each position), and transpositions (swap adjacent characters). This yields O(26 * L) candidates.

3. Efficiently look up candidates

Use a hash set or a trie to check which generated candidates exist in the dictionary. For large-scale systems, consider a precomputed index mapping edit-distance-1 variants to their correct forms, or use a BK-tree for approximate matching.

4. Rank and merge with prefix matches

Score candidates by relevance (e.g., frequency, recency, user behavior) and merge with any existing prefix matches. Use a priority queue to select the top K suggestions, ensuring no duplicates and maintaining order.

5. Optimize for performance and scalability

Cache frequent queries, limit candidate generation to the first few characters if needed, and consider parallelizing lookups. Discuss trade-offs between precomputation and on-the-fly generation.

Key Points to Mention

  • Edit distance 1 operations: deletion, substitution, insertion, transposition
  • Time complexity: O(26 * L) for substitutions, O(L) for deletions/transpositions
  • Data structures: trie, hash set, BK-tree, or precomputed index
  • Ranking strategies: frequency, recency, personalization, and business rules
  • Deduplication and merging with prefix matches
  • Caching and precomputation for low-latency responses

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

Q6

How would you paginate results beyond the top 5 while keeping the ordering stable across requests?

System DesignTechnical Trade-offs
Author's notes

Short question, shorter answer from me.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the data source and access pattern (e.g., SQL database, search index, API). Then explain that stable pagination requires a deterministic total ordering, typically achieved by adding a unique tiebreaker (like a primary key) to the sort key. Finally, describe how to use keyset pagination (seek method) to efficiently fetch results beyond the top 5 without performance degradation.

Pro tip: Mention that offset-based pagination becomes slow and unstable at scale, so for Etsy's large datasets, keyset pagination with a composite cursor (e.g., last sort value + ID) is the preferred approach. Also note that if the sort key is not unique, you must include a tiebreaker to avoid duplicates or missing rows.

1. Clarify requirements and constraints

Ask about the data source, expected data volume, and whether the ordering can change between requests. Confirm that 'stable ordering' means consistent results even if data is inserted or updated.

2. Define a deterministic total order

Ensure the sort key is unique or add a tiebreaker (e.g., primary key) to make the order total. This prevents rows with equal sort values from appearing in different orders across requests.

3. Choose pagination method

Compare offset-based vs. keyset (seek) pagination. Explain that offset is simple but inefficient and unstable for large offsets, while keyset uses a cursor (last seen sort value + tiebreaker) to fetch the next page efficiently.

4. Implement keyset pagination

Describe how to construct the query: WHERE (sort_key, tiebreaker) > (last_sort_value, last_tiebreaker) ORDER BY sort_key, tiebreaker LIMIT page_size. This ensures stable and efficient retrieval beyond the top 5.

5. Handle edge cases and trade-offs

Discuss handling of inserts/updates (e.g., using a snapshot or accepting that new items may appear), and mention that keyset pagination doesn't support random access (jumping to page N).

Key Points to Mention

  • Offset-based pagination is simple but suffers from performance degradation and instability due to shifting data.
  • Keyset pagination (seek method) uses a cursor based on the last row's sort key and a unique tiebreaker.
  • A unique tiebreaker (e.g., primary key) is essential to guarantee a total order and avoid duplicates or missing rows.
  • Composite cursor: (sort_key, tiebreaker) > (last_sort_value, last_tiebreaker) for efficient and stable pagination.
  • Trade-offs: keyset pagination is not suitable for random access (e.g., jumping to page 10) and requires careful handling of updates.
  • For Etsy-scale data, consider indexing the sort key and tiebreaker to support efficient range queries.

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

Q7

What are the edge cases you'd want to stress-test, and how would you handle things like very long shared prefixes, non-ASCII input, or an empty prefix query?

System DesignAlgorithms & Data Structures
Author's notes

I listed a few: empty prefix returning global top-5, very long words causing deep trie traversal, Unicode normalization mismatches.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem context—this is likely about autocomplete or search prefix matching at Etsy scale. Then systematically walk through edge cases (empty, very long, non-ASCII, shared prefixes) and for each, explain the algorithmic and system design implications, such as trie depth, Unicode normalization, and memory/time trade-offs. Conclude with how you'd test and monitor these cases in production.

Pro tip: Tie each edge case to a real Etsy scenario, like a shopper typing an emoji or a long product name, and mention that you'd log and analyze these cases to improve the system. This shows product sense and data-driven thinking.

1. Clarify the problem and context

Ask whether this is for autocomplete, search suggestions, or a general prefix-matching service, and what scale and latency requirements exist. This ensures your answer is relevant to Etsy's use case.

2. Enumerate edge cases

List categories: empty prefix, very long shared prefixes, non-ASCII input, mixed case, whitespace, special characters, and extremely long queries. Explain why each is challenging.

3. Propose handling strategies

For each edge case, describe algorithmic and system-level solutions, such as using a trie with Unicode normalization, limiting prefix length, or falling back to a default set of suggestions.

4. Discuss testing and monitoring

Explain how you'd stress-test these cases (unit tests, fuzzing, load tests) and monitor them in production (logging, dashboards, alerts).

5. Summarize trade-offs and recommendations

Wrap up by highlighting key trade-offs (e.g., memory vs. speed) and recommend a balanced approach that prioritizes user experience and system reliability.

Key Points to Mention

  • Empty prefix: return popular or trending items, but consider personalization and diversity.
  • Very long shared prefixes: use a trie with path compression or a suffix tree to avoid deep traversal; consider caching frequent prefixes.
  • Non-ASCII input: normalize Unicode (e.g., NFC/NFD), handle emojis and diacritics, and ensure tokenization supports multi-byte characters.
  • Performance: limit prefix length, use approximate matching or early termination, and consider distributed caching for hot prefixes.
  • Testing: fuzz testing with random Unicode strings, load testing with high concurrency, and A/B testing for relevance.
  • Monitoring: track query latency, error rates, and fallback frequency; log edge cases for offline analysis.

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