Interview Questions
Redis Interview Questions and Answers
Redis interviews focus on when and how to use it correctly as a cache -- especially cache invalidation strategy, which is where most real production bugs show up.
Example: Cache-aside pattern
Javapublic Product getProduct(Long id) {
String cacheKey = "product:" + id;
String cached = redisTemplate.opsForValue().get(cacheKey);
if (cached != null) {
return deserialize(cached); // cache hit
}
Product product = productRepository.findById(id).orElseThrow();
redisTemplate.opsForValue().set(cacheKey, serialize(product), Duration.ofMinutes(10));
return product; // cache miss -- fetched from DB, then cached
}
Frequently Asked Questions
Lists (ordered, allow duplicates), Sets (unordered, unique members), Sorted Sets (unique members each with a score, kept in score order -- ideal for leaderboards), Hashes (field-value pairs, like a mini object), and Streams (append-only logs for event data).
The application checks the cache first; on a miss, it queries the source database, then writes the result into the cache before returning it (shown in the example above). It's the most common caching pattern because the cache only ever holds what's actually been requested, and the application stays in full control of what gets cached and for how long.
Common approaches: explicitly delete or update the cache key when the source data changes (in the same code path that does the update), or rely on a short TTL (expiry) so stale data self-corrects within a bounded time even if you miss an explicit invalidation. "There are only two hard things in computer science: cache invalidation and naming things" is a cliché for a reason -- getting this wrong causes real, hard-to-debug staleness bugs.
An expiry set on a key (EXPIRE key 600 for 10 minutes, or SET key value EX 600 to set it atomically with the value) -- after that time, Redis automatically removes the key. It's the simplest safety net against serving stale cached data forever if an explicit invalidation is ever missed.
By default it's in-memory, so an unexpected crash or restart can lose recent writes. Even with persistence (RDB snapshots or an append-only file) enabled, it's generally not treated with the same durability guarantees as a dedicated primary database -- most systems use Redis for data that's either disposable (a cache) or has an authoritative copy elsewhere.
A common pattern: use INCR to increment a counter keyed by user+time-window (e.g. rate:user123:2026-07-27T10:15), and set an expiry on that key matching the window length. If the counter exceeds your limit before the key expires, reject the request. Redis's atomic INCR avoids race conditions that a read-then-write approach in application code would have under concurrent requests.
The core command execution is single-threaded (though newer versions offload some I/O to background threads), which is actually part of why it's so fast and predictable -- no locking overhead for concurrent command execution. The practical implication: a single very slow command (like a KEYS * scan on a huge dataset) blocks everything else, which is why KEYS is generally avoided in production in favor of SCAN, which iterates incrementally instead.