← Bytedance Interview Insights

Bytedance·Software Engineer·Technical Phone Screen·Senior

Senior
May 2026

Summary

Bytedance SWE interview that went deep on LRU cache design, then kept pushing further into TTL extensions and thread-safety. More of a design conversation than a pure coding session, which I wasn't fully expecting.

Questions Asked (5)

Q1

Implement an LRU cache with O(1) get and put operations. Walk through your data structure choices.

Algorithms & Data StructuresSystem Design
Author's notes

Started with the hashmap plus doubly linked list combo which is the obvious answer, but they made me actually justify why a singly linked list wouldn't work.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and constraints, then propose a hash map combined with a doubly linked list to achieve O(1) operations. Walk through the design, explaining how get and put work, and discuss edge cases and potential optimizations.

Pro tip: Mention that you'd use a doubly linked list with sentinel head and tail nodes to simplify edge cases and avoid null checks, showing attention to clean code. Also, briefly discuss thread-safety if the cache might be accessed concurrently, as Bytedance often values scalable system design.

1. Clarify requirements and constraints

Ask about expected cache size, concurrency needs, and whether operations must be truly O(1) in all cases. Confirm that the cache should evict the least recently used item when full.

2. Choose data structures

Propose a hash map for O(1) key lookup and a doubly linked list to maintain usage order. Explain that the hash map stores key -> node references, and the linked list orders nodes from most to least recently used.

3. Define operations

Detail how get(key) retrieves the node, moves it to the front (most recently used), and returns the value. For put(key, value), if key exists, update value and move to front; if not, create a new node, add to front, and if capacity exceeded, remove the tail node and delete its key from the map.

4. Handle edge cases and optimizations

Discuss edge cases like capacity 0 or 1, and updating existing keys. Mention using sentinel nodes to simplify list operations. Optionally, talk about thread-safety using locks or concurrent data structures if needed.

5. Analyze complexity and conclude

Confirm that both get and put are O(1) time and O(capacity) space. Summarize the design and offer to write code or discuss further optimizations.

Key Points to Mention

  • Hash map provides O(1) access to cache nodes.
  • Doubly linked list maintains recency order with O(1) insertion and deletion.
  • Sentinel head and tail nodes simplify edge cases.
  • Eviction policy: remove least recently used (tail) when capacity is exceeded.
  • Thread-safety considerations for concurrent access (e.g., using locks or ConcurrentHashMap).
  • Time and space complexity: O(1) for get/put, O(capacity) space.

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

Q2

How would you handle eviction when the cache exceeds its capacity?

Algorithms & Data StructuresSystem Design
Author's notes

Pretty mechanical once you have the linked list set up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: what type of cache, what eviction policies are acceptable, and what are the performance constraints. Then explain common eviction policies like LRU, LFU, and FIFO, and discuss how to implement them efficiently using data structures such as hash maps and doubly linked lists. Finally, mention advanced considerations like concurrency, persistence, and real-world trade-offs.

Pro tip: Demonstrate awareness of real-world systems by referencing how popular caches (e.g., Redis, Memcached) handle eviction, and discuss the trade-offs between different policies in terms of hit rate, implementation complexity, and overhead.

1. Clarify requirements

Ask about the cache type (in-memory, distributed), expected workload (read/write ratio, access patterns), and constraints (latency, memory). This shows you don't jump to solutions without understanding the problem.

2. Choose an eviction policy

Discuss common policies like LRU, LFU, FIFO, and Random. Explain their pros and cons and when each is appropriate. For example, LRU works well for temporal locality, while LFU is better for frequency-based access.

3. Design the data structures

For LRU, describe using a hash map for O(1) access and a doubly linked list to track recency. For LFU, use a min-heap or frequency buckets. Emphasize O(1) operations for get and put.

4. Handle concurrency and edge cases

Mention thread safety (e.g., using locks or lock-free structures), and edge cases like cache stampede, expiration, and size limits. Discuss how to handle eviction when multiple threads access the cache.

5. Evaluate trade-offs and alternatives

Compare policies in terms of hit rate, complexity, and overhead. Mention advanced techniques like ARC, 2Q, or segmented LRU. Also, consider if eviction is even necessary (e.g., using TTL or soft references).

Key Points to Mention

  • LRU implementation with hash map and doubly linked list for O(1) operations
  • LFU and its use of frequency counts, often with a min-heap or frequency lists
  • FIFO and Random eviction policies and their simplicity vs. effectiveness
  • Concurrency considerations: locking, lock-free caches, and thread-safe eviction
  • Real-world examples: Redis maxmemory-policy, Memcached LRU, and Guava Cache
  • Trade-offs: hit rate vs. implementation complexity, and when to use approximate algorithms like LRU-K or TinyLFU

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

Q3

Extend the cache to support per-entry TTL. What are your options for expiring entries?

System DesignTechnical Trade-offs
Author's notes

This is where it got interesting.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: is this a single-node cache or distributed? What are the latency and consistency needs? Then present multiple expiration strategies, comparing their trade-offs in terms of accuracy, overhead, and complexity, and finally recommend a hybrid approach that balances efficiency and precision.

Pro tip: Mention that lazy expiration alone can cause memory bloat and that active expiration must be carefully tuned to avoid CPU spikes; a combination with probabilistic early expiration can further reduce latency spikes.

1. Clarify requirements and constraints

Ask about the cache type (in-memory, distributed), scale, latency requirements, and whether TTL precision is critical. This ensures your answer is tailored to the context.

2. Outline expiration strategies

Present the main options: lazy expiration (on access), active expiration (background sweeper), and hybrid approaches. Briefly explain how each works.

3. Compare trade-offs

Discuss pros and cons: lazy expiration is simple but can cause stale data and memory bloat; active expiration is timely but adds CPU overhead; hybrid balances both but adds complexity.

4. Consider implementation details

Mention data structures (e.g., min-heap for active expiration, timing wheel), concurrency concerns, and how to handle eviction policies (e.g., LRU with TTL).

5. Recommend a solution

Propose a hybrid approach: lazy expiration on read plus a background sweeper that runs periodically, possibly with probabilistic early expiration to smooth out spikes.

Key Points to Mention

  • Lazy expiration: check TTL on access, delete if expired; simple but can leave expired entries in memory.
  • Active expiration: background process scans and removes expired entries; timely but may impact performance.
  • Hybrid approach: combine lazy and active for efficiency and timeliness.
  • Data structures: min-heap or timing wheel for efficient expiration tracking.
  • Concurrency: ensure thread-safe operations when expiring entries.
  • Eviction policies: integrate TTL with LRU/LFU to handle capacity limits.

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

Q4

What are the trade-offs between lazy expiration and active expiry with a background process?

Technical Trade-offsSystem Design
Author's notes

Lazy is simple and has no CPU overhead when nothing is being accessed, but stale entries sit in memory and could cause problems under high load or tight memory budgets.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining both expiration strategies and their core mechanisms, then systematically compare them across dimensions like latency, CPU/memory overhead, and consistency. Conclude with practical recommendations for when to use each, ideally tied to real-world systems like Redis or Memcached.

Pro tip: Mention that hybrid approaches (e.g., lazy expiration with periodic active sweeps) are common in production systems, and that the choice often depends on workload patterns and SLA requirements.

1. Define the strategies

Briefly explain lazy expiration (check on access) and active expiration (background process scanning and removing expired keys).

2. Compare on latency and CPU

Discuss how lazy expiration adds latency to reads (due to checks) but saves CPU, while active expiration uses background CPU to keep reads fast.

3. Compare on memory usage

Explain that lazy expiration can lead to memory bloat from expired-but-unaccessed keys, whereas active expiration reclaims memory promptly.

4. Consider consistency and edge cases

Address how each handles expired keys in replicas, persistence, and concurrent access, and potential issues like stale reads.

5. Recommend based on use case

Suggest when to use each: lazy for read-heavy with infrequent writes, active for memory-sensitive or write-heavy workloads, and hybrids for balance.

Key Points to Mention

  • Lazy expiration avoids background CPU but can cause memory leaks and increased latency on access.
  • Active expiration keeps memory clean but consumes CPU and may impact throughput if not tuned.
  • Hybrid approaches (e.g., Redis) combine both to balance latency and memory.
  • Consideration of eviction policies and maxmemory settings when discussing memory.
  • Impact on replication and persistence: expired keys may still be propagated or saved.
  • Trade-offs in distributed systems: active expiration may cause contention or coordination overhead.

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

Q5

How would you make this cache thread-safe?

System DesignTechnical Trade-offs
Author's notes

Talked through a global lock first as the naive approach, then reader-writer locks to allow concurrent reads, then briefly touched on sharding the cache into segments to reduce contention.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the cache's usage pattern (read/write ratio, concurrency level) and the required consistency guarantees. Then propose a thread-safety strategy, such as fine-grained locking or lock-free techniques, and discuss trade-offs between performance, complexity, and correctness.

Pro tip: Mention that thread-safety often involves choosing between blocking and non-blocking algorithms, and that the best choice depends on the specific workload—demonstrating you consider real-world constraints rather than just reciting textbook solutions.

1. Clarify Requirements

Ask about the cache's expected read/write ratio, concurrency level, and consistency requirements (e.g., strong vs. eventual). This ensures your solution aligns with the actual use case.

2. Identify Shared State

Determine which data structures are shared and mutable (e.g., hash map, LRU list). This helps pinpoint where synchronization is needed.

3. Choose Synchronization Strategy

Select an appropriate technique: coarse-grained locks (simple but low concurrency), fine-grained locks (better concurrency but complex), or lock-free approaches (e.g., atomic operations, concurrent data structures).

4. Address Common Pitfalls

Discuss issues like deadlocks, race conditions, and memory consistency. Mention how to avoid them, e.g., lock ordering, using immutable objects, or leveraging language-specific concurrency utilities.

5. Evaluate Trade-offs

Compare your chosen approach against alternatives in terms of performance, scalability, and code complexity. Justify why your solution is optimal for the given context.

Key Points to Mention

  • Read-write locks to allow concurrent reads while ensuring exclusive writes.
  • Concurrent data structures like ConcurrentHashMap or striped locks for fine-grained synchronization.
  • Lock-free techniques using atomic operations (e.g., CAS) for high-performance scenarios.
  • Trade-offs between throughput, latency, and implementation complexity.
  • Consistency models (e.g., linearizability, eventual consistency) and their impact on design.
  • Testing and validation strategies for thread safety, such as stress testing and race detection tools.

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