← Meta Interview Insights

Meta·Software Engineer·Onsite - Coding / Algorithms·Senior

SeniorPrefer not to say
Apr 2026

Summary

Meta SWE onsite coding round, basically a warm-up question that still has enough sharp edges to trip you up if you haven't drilled it recently. The follow-ups are where they actually separate candidates.

Questions Asked (4)

Q1

Implement an LRU Cache with O(1) get and put operations, including capacity-based eviction.

Algorithms & Data Structures
Author's notes

Classic LC 146.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use a hash map for O(1) key lookup and a doubly linked list to maintain usage order, with the most recently used at the head and least recently used at the tail. For get, move the accessed node to the head; for put, add or update the node at the head and evict the tail if capacity is exceeded.

Pro tip: Mention that you can implement the doubly linked list manually or use an ordered dictionary (like LinkedHashMap in Java or OrderedDict in Python) to simplify, but be prepared to explain the underlying mechanics. Also, discuss thread-safety considerations if the cache will be used in a concurrent environment.

1. Clarify requirements and constraints

Ask about expected capacity, concurrency needs, and whether keys/values are generic. Confirm that get and put must be O(1) and that eviction is based on least recent use.

2. Design the data structures

Choose a hash map for O(1) access and a doubly linked list for O(1) insertion/deletion. Explain how they work together: map stores key -> node, list maintains order.

3. Define operations and edge cases

Detail get: if key exists, move node to head and return value; else return -1. Detail put: if key exists, update value and move to head; else create new node, add to head, and if size > capacity, remove tail and delete from map.

4. Implement and test

Write clean code with helper functions for add/remove node. Test with scenarios: empty cache, single item, eviction, updating existing key, and capacity 1.

5. Analyze complexity and discuss optimizations

Confirm O(1) time for both operations and O(capacity) space. Mention potential optimizations like using a sentinel head/tail to simplify edge cases or considering thread-safe variants.

Key Points to Mention

  • Hash map provides O(1) key lookup, doubly linked list provides O(1) node removal and insertion.
  • Most recently used (MRU) at head, least recently used (LRU) at tail for easy eviction.
  • On get, move accessed node to head to mark as recently used.
  • On put, if key exists, update value and move to head; if new, add to head and evict tail if over capacity.
  • Use sentinel nodes (dummy head and tail) to avoid null checks and simplify edge cases.
  • Time complexity: O(1) for both get and put; space complexity: O(capacity).

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

Q2

How would you make the LRU Cache thread-safe? What are the tradeoffs between a coarse lock and a more granular approach?

Technical Trade-offsSystem Design
Author's notes

Came up as a follow-up.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the LRU cache operations and their thread-safety requirements, then propose a coarse-grained lock as a baseline and a more granular approach using separate locks for the hash map and the linked list. Compare the tradeoffs in terms of contention, complexity, and performance, and justify your choice based on expected workload.

Pro tip: Mention that you would first measure contention under realistic workloads before optimizing, and consider using existing thread-safe libraries (e.g., Java's ConcurrentHashMap and a concurrent linked list) to avoid reinventing the wheel.

1. Clarify requirements and assumptions

Confirm the expected read/write ratio, concurrency level, and whether the cache must be strictly LRU or can be approximate. This sets the stage for choosing the right synchronization strategy.

2. Describe coarse-grained locking

Explain using a single mutex to protect all operations (get, put). This is simple and correct but serializes all accesses, causing high contention and poor scalability.

3. Describe fine-grained locking

Propose separate locks for the hash map and the doubly linked list, or lock striping on the map. Detail how to avoid deadlocks by acquiring locks in a consistent order and handling concurrent evictions.

4. Compare tradeoffs

Discuss performance vs. complexity: coarse lock is easy but slow under high concurrency; fine-grained improves throughput but adds overhead, risk of deadlocks, and subtle bugs. Mention alternatives like lock-free or read-write locks.

5. Recommend and justify

Choose an approach based on the workload. For low contention, coarse lock suffices; for high contention, fine-grained or lock-free is better. Emphasize measuring and iterating.

Key Points to Mention

  • Coarse-grained lock: single mutex, simple but serializes all operations, poor scalability.
  • Fine-grained locking: separate locks for map and list, or lock striping, reduces contention but increases complexity.
  • Deadlock avoidance: consistent lock ordering, try-lock with timeouts, or lock-free algorithms.
  • Read-write locks: allow concurrent reads but writes still exclusive; may improve read-heavy workloads.
  • Performance metrics: throughput, latency, contention; measure before optimizing.
  • Existing solutions: use ConcurrentHashMap and a concurrent linked list, or libraries like Caffeine.

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

Q3

Can you extend this to an LFU Cache? How does the eviction logic change?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Stretch goal territory.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the LFU eviction policy: evict the least frequently used item, breaking ties by least recently used. Then, explain how to extend the LRU cache design by adding a frequency tracking mechanism, such as a min-heap or a frequency map with doubly linked lists, and discuss the trade-offs in time and space complexity.

Pro tip: Mention that LFU is more complex than LRU and often requires a combination of data structures (e.g., frequency map + doubly linked lists) to achieve O(1) operations, and highlight that real-world systems sometimes use hybrid policies like LRU-K or LFU with aging to avoid cache pollution.

1. Clarify LFU semantics

Define LFU: evict the item with the lowest access frequency; if multiple items have the same frequency, evict the least recently used among them (LRU tie-breaker).

2. Identify required data structures

To achieve O(1) operations, use a frequency map where each frequency points to a doubly linked list of items with that frequency, plus a min-frequency pointer to track the lowest frequency.

3. Explain eviction logic

On eviction, remove the least recently used item from the list at the min-frequency. If that list becomes empty, increment the min-frequency pointer to the next non-empty frequency.

4. Handle access and insertion

On access, move the item to the next higher frequency list and update the min-frequency if needed. On insertion, add the new item to the frequency-1 list and set min-frequency to 1 if necessary.

5. Discuss trade-offs and optimizations

Compare LFU with LRU: LFU better retains frequently used items but can suffer from cache pollution and stale entries. Mention optimizations like frequency aging or using a heap for simpler but O(log n) operations.

Key Points to Mention

  • LFU evicts the least frequently used item, with LRU as a tie-breaker.
  • O(1) implementation uses a frequency map of doubly linked lists and a min-frequency pointer.
  • On access, item moves to the next frequency list; min-frequency may need updating.
  • On insertion, new items start at frequency 1; if cache is full, evict from min-frequency list.
  • Trade-offs: LFU can be more accurate but has higher overhead and potential cache pollution.
  • Real-world systems may use hybrid policies (e.g., LRU-K, LFU with aging) to mitigate issues.

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

Q4

How would you add TTL (time-to-live) expiration to the cache?

System DesignTechnical Trade-offs
Author's notes

Brief mention, didn't go deep.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the cache's architecture and requirements (e.g., in-memory vs. distributed, consistency needs). Then propose a TTL mechanism, such as lazy expiration with periodic cleanup, and discuss trade-offs like memory overhead, eviction policies, and clock skew. Finally, mention how to handle edge cases like stale reads and thundering herd.

Pro tip: At Meta, scale and latency matter: emphasize that TTL should be configurable per key and that expiration should be probabilistic to avoid synchronized spikes. Also, consider using a hierarchical timer wheel for efficient expiration in large caches.

1. Clarify requirements and constraints

Ask about the cache type (in-memory, distributed), consistency requirements, expected scale, and whether TTL is per-key or global. This ensures your solution fits the context.

2. Choose an expiration strategy

Decide between lazy expiration (check on access) and active expiration (background sweeper). Often a hybrid approach works best: lazy check plus periodic cleanup.

3. Implement TTL storage and eviction

Store expiration timestamps alongside values. For active expiration, use a min-heap or timer wheel to efficiently find expired entries. For lazy, check timestamp on read and delete if expired.

4. Handle concurrency and edge cases

Ensure thread-safe access to expiration data. Address clock skew in distributed systems by using a central time source or logical clocks. Prevent thundering herd by adding jitter to TTLs.

5. Discuss trade-offs and optimizations

Compare memory overhead vs. CPU cost of active expiration. Consider eviction policies (LRU, LFU) interacting with TTL. Mention monitoring and tuning TTL values based on access patterns.

Key Points to Mention

  • Lazy vs. active expiration and hybrid approaches
  • Data structures for efficient expiration (min-heap, timer wheel, timing wheel)
  • Concurrency control (locks, lock-free structures) for thread safety
  • Clock skew and distributed time synchronization (e.g., using NTP or logical clocks)
  • Thundering herd mitigation via TTL jitter
  • Interaction with eviction policies and memory management

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