Implement an In-Memory Key-Value Cache with Expiry, Then Sketch a Redis-Like Server
CrowdstrikeSoftware Engineer · OnsiteLast updated
Implement an in-memory key-value cache in the spirit of Redis, with get, set, delete and per-key expiry, then briefly discuss how a Redis-like server is built and where caches fit in a system. It tests data structure choices, expiry and eviction logic, thread safety, and practical knowledge of caching patterns.
Implement an in-memory key-value cache that behaves like a small subset of Redis, then spend a few minutes on how you would design a Redis-like system and where a cache like this is useful. The design portion is brief and mainly checks your knowledge of how caches are used; most of the time goes to writing working code.
Constraints and Clarifications
- Assume single-process, in-memory storage; persistence and networking belong to the design discussion, not to the code.
- Keys are strings. Values can be any object unless the interviewer narrows them.
- Ask before adding features: the set of operations, expiry semantics, a size limit and concurrent access are all open until confirmed.
Clarifying Questions
- Which operations are required: get, set and delete only, or also counters, existence checks and key listing?
- Should keys support a time-to-live, and is expiry measured from the last write or the last read?
- Is there a limit on the number of entries or on memory, and which keys go first when it is reached?
- Will several threads use the cache at the same time?
- How should a lookup of a missing or expired key be reported?
Part 1 — Implement the cache
Write a cache class that supports at least set(key, value, ttl=None), get(key) and delete(key), where a key written with a ttl stops being visible once that many seconds have passed. If the interviewer adds a capacity limit, evict entries by a policy you choose and justify. State the complexity of each operation and show how you would test expiry without waiting in real time.
What This Part Should Cover
- Correct expiry semantics, including keys that are overwritten or deleted before they expire
- Data structures that keep get, set and delete fast, with complexity stated
- A capacity and eviction policy if one is required, and safe behavior under concurrent access
- Tests that control time instead of sleeping
Part 2 — Sketch a Redis-like system and its uses
Briefly describe how you would turn the cache into a networked service in the spirit of Redis: how clients talk to it, how commands are executed, how data survives a restart, and how it scales beyond one machine. Then describe the situations in which you would put a cache like this in front of other systems, and the problems caching introduces.
What This Part Should Cover
- The request-handling and execution model, and how it makes each command atomic
- Persistence options and replication, with their durability trade-offs
- Common cache use cases and patterns such as cache-aside and write-through
- Caching hazards: invalidation, stale reads, stampedes and hot keys
Hints
Hint 1
Two ways to forget a key: An expired key can be removed when someone asks for it or proactively in the background; consider what each approach costs in time and memory, and whether you need both.
Hint 2
Where the time goes: Consider how long a command against in-memory data actually takes compared with moving bytes over the network, and what that implies for how many threads need to touch the data.
Follow-up questions
- How would you add an atomic increment operation, and why does atomicity matter for it?
- How would you approximate least-recently-used eviction cheaply when there are millions of keys?
- What changes if values vary widely in size and the limit is on memory rather than on entry count?
- How would you keep the cache consistent with the database it fronts when both are updated?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.