Why this matters: everyone has "implement an LRU cache" filed away as a LeetCode exercise, and that's exactly the trap. The interview version is a library design round: the API and its promises are the product, and half the scoreable decisions — what capacity means, whether a read refreshes recency, what an update does at the limit — are made in the requirements conversation, before a single node gets linked.
The prompt, as given
Design an in-memory cache library.
Other services will embed your library directly in their process: they put values in, get them back, and trust the cache to stay within a capacity bound by evicting something when it must.
Notice what's missing: what "capacity" is measured in, which operations exist, what eviction means, what happens on an update. The candidate who starts drawing a hash map and a linked list is answering a question the interviewer hasn't asked yet. The candidate who asks the right six questions is already scoring.
The questions, and why each one matters
"What does capacity mean — entries or bytes?" This one question splits the design in two. An entry count means the cache can count; a byte budget means someone has to know how big a value is, and that someone is probably not your library. Pin it first, because everything about eviction timing hangs on it.
"Which operations, exactly?" Get, put, remove — and just as important, what's not there. No iteration and no bulk operations means your internal ordering never has to be exposed, which is freedom you'll spend later.
"Does a read count as a use?" The heart of "least recently used." If get refreshes an entry's standing, your reads are writes to the recency bookkeeping — that's a real structural consequence, not a nicety. And the twin question: does updating an existing key count as a use too?
"When does eviction actually happen?" The precise trigger matters: on inserting a new key at capacity? On every put? Does updating an existing key ever evict? A crisp answer here is the difference between an eviction path you can enforce invariants around and one that fires "whenever."
"Are null values allowed?" Sounds pedantic, is not: if null can be a stored value, then get returning null is ambiguous between miss and stored nothing, and your API needs a second channel. Banning nulls buys an unambiguous miss signal for free.
"Is this concurrent?" Ask so you can name the assumption out loud. A single-threaded v1 is a perfectly good design round — silently assuming it is not.
"Does anyone need to know how the cache is doing?" Operators almost always want a hit-rate readout. If stats are in scope, hits and misses need a home and a definition — deciding what counts as a hit is API design, not an afterthought.
The requirement set this chapter builds against
Capacity maximum ENTRY COUNT, fixed at construction
Operations get(key), put(key, value), remove(key) — no iteration
Recency get refreshes an entry's standing;
put on an existing key updates the value AND refreshes
Eviction only when a put of a NEW key would exceed capacity;
victim = least recently used; updates never evict
Null values disallowed — get returning null means miss, always
Stats hit/miss counters with a hit-rate readout
Threading single-threaded (stated assumption)
The design latent in this table: recency refresh on every get means the "used" bookkeeping sits on the hot read path, so it had better be O(1). The new-key-only eviction trigger means put has two genuinely different paths. And the stats requirement means "hit" needs a definition your counters can enforce.
As with every chapter in this course: a live interviewer's answers may differ. Maybe their capacity is a byte budget, maybe updates don't refresh. The skill is the conversation — ask the questions for these reasons, and a different answer sheet just steers the same method to a slightly different design.
Key takeaway
The cache round is won at the API before it's won at the data structure. Pin what capacity counts, the exact get/put/remove semantics — does a read refresh recency, does an update ever evict — the null policy that keeps the miss signal unambiguous, the threading assumption, and whether stats are in scope. This chapter builds against one representative answer set; the questions, not the answers, are the reusable part.