Katkat

Implement an In-Memory Key-Value Cache with Expiry, Then Sketch a Redis-Like Server

CrowdstrikeSoftware Engineer · Onsite

Last 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?