RedisVisualInterview prep

Stop 7 · Interview prep

Turn what you learned in the earlier stops into English you can say to an interviewer.

Interview prep

The question, a model answer, and why it works

The earlier stops covered what is, why it is fast, how a real system uses it, and how caches fail. This stop turns that into words you can say out loud: every question comes with an English model answer you can rehearse, plus a short note on what the interviewer is checking and which sentence loses credit. Click any question to open it. Words with a dotted underline open a short definition.

26 questions26 common questions, ordered fundamentals → system → advanced. Read them from top to bottom.

Model answer

Redis is an in-memory data store. The name comes from REmote DIctionary Server, so you can picture one large dictionary that many programs read and write over the network. Because the data sits in , reads and writes are very fast. Teams use it for caching, counters, session storage, rate limiting, and leaderboards. In our system it sits in front of the database, so it holds data that has to be fast and is allowed to be short-lived.

Why this works

The interviewer is checking whether you can define the tool in one sentence before you talk about it. Credit comes from two words: data store, and in-memory. Every later question builds on the second one, so say it early. The trap is reciting the whole feature list; three or four real use cases are enough, and then you stop and let them choose the follow-up.

Model answer

Three reasons, and memory is only the first one. The data is in , so there is no disk read. The command path is also short: a GET is close to a hash-table lookup, while SQL has to parse the query, plan it, walk a B+ tree, and apply transaction rules. And Redis runs commands one at a time on a , so it needs no locks between them. That is why MySQL with a warm buffer pool is still slower: it does more work per request.

Why this works

This is the most common follow-up in the whole set. The interviewer will answer that MySQL also keeps pages in memory, so memory alone cannot be the reason. Credit comes from the second point: Redis does far less work per command. One thread and no locking is a good third point, but do not let it become a claim that Redis is single-threaded everywhere, because Redis 6 added threads for network I/O.

Model answer

It can be both. Redis supports persistence, so some teams run it as a primary store. In most systems, including ours, it is a cache and a read model in front of a durable database. It is not the . If we lost the whole Redis instance, we could rebuild every key from the database.

Why this works

The interviewer wants a position, not a definition. Say that it can be either, then say which one it is in your system and why. Credit comes from naming the source of truth out loud, because that decides how you answer the failure question later. The trap is an abstract answer that never says what you actually built.

Model answer

A means the value is already in the cache, so you return it right away and skip the slow query or the external call. A means it is not there, so you read the original source and then write the result back, so the next request hits. A miss is a normal part of the flow, not an error. The number that matters is hit rate, which is hits divided by total lookups. If the hit rate is low, the cache is using memory and returning very little.

Why this works

This is a warm-up question, so answer it quickly and add one thing the definition does not contain. Hit rate is that thing, and naming it suggests you have watched a cache in production rather than read about one. The trap is calling a miss an error; a miss is the normal path that fills the cache in the first place.

Model answer

, time to live, is an expiry timer on a key. Once the key expires, Redis will not return it any more. The deletion can happen slightly later, because Redis checks expiry when a key is accessed and a background job samples keys that carry a TTL. Caches depend on this, so stale values do not stay forever. Our rate cache uses a short TTL: a shipping quote is only valid for a short time, so expiry is part of correctness and not only cleanup.

Why this works

Give the definition, then be precise about the guarantee. Redis promises that an expired key is not returned; it does not promise the key is removed at that exact moment, and the memory is reclaimed later. Saying that a short TTL is also a correctness rule, not only cleanup, shows you think about the data and not only about the cache. The trap is claiming the key disappears the instant the timer ends.

Model answer

The five core types are strings, hashes, lists, sets, and sorted sets. A string holds a value or a counter. A hash stores an object as fields, so you can update one field without rewriting the whole object. A list works as a queue or a stack, and a set gives you membership tests and deduplication. A sorted set keeps members ordered by a score, which is what leaderboards and sliding-window rate limiting need. There are more types, such as streams, bitmaps, and HyperLogLog, but those five cover most daily work.

Why this works

The interviewer is checking whether you can map a structure to a problem, not whether you can list names. Give one short use case per type, and make the sorted set example concrete, because leaderboards and rate limiting are the two that sound like real work. Naming streams or HyperLogLog shows wider reading, but do not start explaining them unless you are asked. The trap is a flat list with no use cases attached.

Model answer

In three places. First, a cache for shipping rate quotes with a short , so repeated lookups for the same package do not call the APIs again. Second, an key on label purchase using , so a retry or a double click cannot charge the customer twice or create two labels. Third, an account balance : the in the database stays the source of truth, and Redis holds the pre-computed balance so reads are fast. So one read cache, one concurrency guard, and one read model.

Why this works

This is the answer to rehearse first, because most follow-up questions branch off it. Give the pattern and the problem it solved for each place, then close with the one-line summary, so the interviewer hears three different jobs instead of one vague cache. Be honest about scope: describe only the parts you built, and if one of the three was a design you proposed rather than shipped, say so in the same sentence. The interviewer will pick one and go three levels deeper, so only list the ones you can defend.

Model answer

Because each customer has different negotiated rates with the carriers. If the key contained only the package and the route, I could return customer A's discounted price to customer B. That is a wrong quote and a leak of pricing data at the same time. Putting the accountId in the key keeps every cached quote scoped to the account it was computed for.

Why this works

This looks like a naming question, but the interviewer is testing whether you think about tenant isolation. Credit comes from naming the consequence rather than the rule: without the accountId, one customer can be shown another customer's negotiated price. Adding that this is a data leak, not only a stale value, raises the answer. The trap is answering only that cache keys have to be unique.

Model answer

They cache at different layers. The Apollo Client cache lives in the browser, serves one user, and avoids refetching the same GraphQL data in the frontend. Redis lives on the server, is shared by every user and every server instance, and avoids repeating expensive backend work such as API calls. So one is per user and client-side, and the other is shared and server-side. They do not replace each other, and one request can benefit from both.

Why this works

Answer along three axes: which layer, who it serves, and what work it saves. Credit comes from the shared part, because a server cache helps every user and every instance while a browser cache cannot. The trap is treating them as two options to choose between; they sit at different layers and are normally used together.

Model answer

It depends on the usage, because each one degrades differently. For the rate cache we skip Redis and call the APIs directly: slower, but still correct and available. For the balance we recompute from the , which is the source of truth. Idempotency is the sensitive one, because a lost key could let a duplicate charge through. So it is backed by a unique constraint in the database and by the order status, and correctness never depends on a volatile key surviving.

Why this works

This question is about graceful degradation, and the good answer is not one answer but three. Go usage by usage: the cache degrades to a slow path, the projection is recomputed from the ledger, and the idempotency key needs a durable backstop because losing it can cost real money. Credit comes from that third one, since it shows you know which failure is expensive. The trap is a single sentence such as fall back to the database, which hides the case where falling back is not safe.

Model answer

means stopping the cache from serving a value after the underlying data has changed. The simplest form is: on a write, update the database and then delete the key, so the next read misses and reloads from the source. In our system short TTLs do most of this work, so an entry cannot drift for long. It is a hard problem because the failure is silent: nothing crashes, you simply return data that is out of date.

Why this works

The interviewer wants to hear two things: that you delete the key on a write rather than rewrite it, and that you know why this bug class is dangerous. Credit comes from the word silent, because an invalidation bug raises no error and monitoring does not see it, so users find it first. Closing with the short TTL as your backstop is honest and concrete. The old joke about two hard things in computer science can be mentioned once, but it is not an answer.

Model answer

A happens when many requests miss the same key at the same moment and all rebuild it together. The usual cause is a popular key that has just expired: for a short moment the cache holds nothing, so the full load reaches the database or the API. The fixes are a lock or single flight, so one request rebuilds while the others wait, request coalescing in the service layer, and refreshing the value shortly before it expires instead of after. This is about one key. Many keys expiring at once is a different problem, an avalanche, with a different fix.

Why this works

The interviewer wants the mechanism, not the label: a burst of concurrent misses on one key, at the exact moment the cache was supposed to protect the source. Credit comes from naming a fix that limits concurrency, such as a lock or single flight, because that is the one that caps how many requests reach the source. Keep it separate from an avalanche, which is many keys expiring together. If you have not built one of these, say which one you would choose and why, rather than implying you shipped it.

Model answer

You could, but it is the wrong tool for this data. Rate quotes are temporary, read very often, and meant to expire, which is exactly the shape of a cache entry. In I would have to write my own expiry job, and I would add read load and row churn to the database that the real data depends on. I would still not get memory-speed reads. Redis provides the expiry and the fast reads directly, and keeps this short-lived traffic away from the database.

Why this works

The interviewer is checking how you choose a tool, so answer with the shape of the data: temporary, read-heavy, and meant to expire. Credit comes from the cost you avoid on the database side, not from the claim that Redis is fast. Do not argue that MySQL is bad. The point is fit, and the same reasoning keeps durable financial data in MySQL.

Model answer

I would scope the number carefully. It compares response time for the same package and the same route, before and after caching, on repeated requests, which are the ones a cache can serve. It is not a claim that every request became 40% faster, because the first, uncached request still pays the full cost. And if I did not have real before-and-after measurements, I would not quote a p50 or p95 figure. I would rather take the number off my resume than defend one I cannot support.

Why this works

This question decides whether the interviewer trusts the rest of your resume. Say the scope out loud first: same package, same route, repeated requests only, measured before and after the cache. If you never measured it, say so in plain words — I did not measure that, it was a rough comparison — and then say how you would measure it now. Never invent a p50 or p95 under pressure, because the next question is how you measured it and with what sample size, and an invented number does not survive two follow-ups. If you cannot support the 40%, take it off the resume before the interview.

Model answer

Redis has two persistence options. RDB writes a point-in-time snapshot of the dataset: the file is compact and restart is fast, but a crash between two snapshots loses everything written since the last one. AOF appends every write command to a log, and appendfsync decides how often that log is flushed to disk. The default, everysec, can lose about one second of writes, and the file is larger and slower to replay. Many teams run AOF with everysec, or both mechanisms together. Either way this is crash recovery, not a durability guarantee — the database is still the .

Why this works

Keep the two mechanisms apart: RDB is a snapshot, AOF is a log of write commands. Credit comes from stating the loss window for each one: back to the last snapshot for RDB, about one second for AOF with everysec. Adding that production setups often run AOF everysec, or both, shows you have seen a real configuration. Do not say AOF is simply better, and do not let persistence turn into a claim that Redis is a durable primary database.

Model answer

Redis combines two strategies. Lazy expiration: when a key is accessed, Redis checks the and, if the key has expired, it is removed and not returned. Lazy expiration alone would hold memory for keys that nobody reads again, so there is also active expiration: a background job repeatedly samples keys that carry a TTL and removes the expired ones. So the guarantee is that an expired key is never returned, not that it is deleted at the exact second it expires. Redis avoids a timer per key on purpose, because millions of timers would cost more than sampling.

Why this works

The interviewer is listening for both halves, lazy and active, and for the guarantee behind them. Credit comes from the precise claim: an expired key is not returned, and the memory is reclaimed later. Explaining why there is no timer per key, because the bookkeeping would cost more than sampling, is the design-level point. The trap is saying keys are deleted the moment they expire, which the sampling design does not promise.

Model answer

Eviction only starts when Redis reaches the maxmemory limit, and maxmemory-policy decides what happens then. The default is noeviction: reads keep working and writes return an error. The allkeys-lru and allkeys-lfu policies can evict any key, while the volatile policies only evict keys that carry a . LRU drops what has not been used recently; LFU drops what is used least often, so a one-off scan of cold data pushes less useful data out. Both are approximate: Redis samples a small number of keys and evicts the best candidate instead of keeping an exact ordering. For a pure cache I would use allkeys-lru or allkeys-lfu.

Why this works

Start with the trigger, because eviction and expiry get mixed up: eviction happens at maxmemory, while expiry happens key by key from its own TTL. Credit comes from two contrasts, allkeys versus volatile and LRU versus LFU. The detail that both are sampled approximations rather than exact orderings separates you from a candidate who read one blog post. The trap is answering that Redis deletes old data when memory is full, which skips the policy entirely.

Model answer

They solve three different problems. Replication copies a primary to one or more replicas, which gives read capacity and a standby copy, but replication is asynchronous, so a replica can return slightly stale data. Sentinel adds availability: it watches the primary and promotes a replica automatically when the primary fails. Cluster adds horizontal scale: the keyspace is sharded across 16384 hash slots spread over several primaries. The short version is that Sentinel is failover without sharding, and Cluster is sharding with failover. In both cases a failover can lose recent writes, because the promoted replica may not have received them yet.

Why this works

The interviewer is checking whether you know which problem each one solves, so lead with read capacity, availability, and scale. The line that earns the credit is the contrast: Sentinel is failover without sharding, Cluster is sharding with failover. Adding that replication is asynchronous, so a failover can lose already acknowledged writes, turns a memorized comparison into an engineering answer. The trap is presenting Cluster as an upgraded Sentinel; they answer different questions.

Model answer

Yes, but not in the SQL sense. MULTI queues the commands and EXEC runs them in order, with no other client's command in between. There is no rollback: if one command fails at runtime, the commands around it still take effect. WATCH gives you optimistic concurrency control rather than a lock — if a watched key changed before EXEC, EXEC returns nil, nothing runs, and your code retries. When several steps really have to be one unit, I use a Lua script, which Redis runs as a single unit.

Why this works

Confirm that transactions exist, then correct the expectation the word creates. Credit comes from two precise statements: MULTI and EXEC give ordering and isolation but no rollback, and WATCH is optimistic concurrency, so your code has to handle a nil reply and retry. Naming Lua as the tool for logic that is genuinely multi-step is the strongest part of the answer. Never say a Redis transaction can be rolled back; that one sentence undoes the rest.

Model answer

They are often confused, but they solve different problems. A pipeline is a network optimization: you send many commands without waiting for each reply, then read the replies together, which removes most of the round trips. A pipeline gives no — another client's commands can still run between yours. A transaction, MULTI and EXEC, guarantees that the queued commands run in order with nothing in between. So a pipeline is about round trips and a transaction is about ordering, and you can send a MULTI and EXEC block inside a pipeline.

Why this works

The interviewer is checking one specific misconception: that batching makes commands atomic. Say plainly that a pipeline only removes round trips and that another client can still run commands in between. Credit comes from compressing the contrast into one line: round trips versus ordering. Adding that a transaction can be sent inside a pipeline shows you have used both rather than read about them.

Model answer

The basic pattern is . NX means the write only succeeds if the key does not exist, so exactly one client acquires the lock, and PX sets the timeout. Two details matter. To release, do not call DEL directly: run a small Lua script that checks the stored value is yours and deletes it in the same step, otherwise you can delete a lock that another client acquired after your TTL expired. And a lock on a single Redis instance is not safe across a failover, because replication is asynchronous and a promoted replica may never have received the lock. If correctness has to be absolute, I would use a system built for consensus instead.

Why this works

Three layers earn credit: acquire with one command that both checks and sets, release with a compare-and-delete Lua script, and a TTL so a crashed client cannot hold the lock forever. If the work can outlive the TTL, mention a watchdog that renews it. What the interviewer is really listening for is the limit: a single-instance lock can be lost during a failover, because replication is asynchronous. Redlock is worth naming if they ask about multiple primaries, but present it as debated rather than as a fix — Kleppmann's critique about clock drift and process pauses is the standard reference.

Model answer

Penetration is when requests ask for data that does not exist anywhere. The cache misses every time because there is nothing to store, so every request reaches the database and the cache gives no protection at all. It can also be abused, by sending random ids that will never exist. The fixes are to cache the empty result with a short , to put a Bloom filter in front so ids that certainly do not exist are rejected early, and to validate the id format before any lookup.

Why this works

The interviewer is checking whether you can separate the three cache failures, so define this one by its cause: the data does not exist, so no cache can ever hold it. Credit comes from caching the empty result with a short TTL, the fix most candidates forget. Mentioning that a Bloom filter can say no for certain but not yes for certain is a good extra detail. Do not mix this with a hot key expiring, which is breakdown.

Model answer

Breakdown is about one key that exists and is very popular. When that key expires, the requests that were being served from cache all miss within the same moment and reach the database together. The fixes are a mutex or single flight so one request rebuilds while the others wait, logical expiry where you keep serving the old value and rebuild in the background, or never expiring the hottest keys and refreshing them on a schedule.

Why this works

Define it by the two conditions the interviewer is listening for: the key exists, and it is hot. Credit comes from a fix that limits how many requests rebuild the value, so name the mutex or single-flight version first. Logical expiry is the answer if they push on latency, because then no request waits for the rebuild. The trap is describing many keys expiring together, which is avalanche.

Model answer

An avalanche is the large-scale version: a large number of keys expire at nearly the same time, or the Redis node itself fails, so a big share of the traffic reaches the database at once. The classic cause is filling the cache in one batch with an identical . The fixes are random jitter on the TTLs so keys expire at different times, a second cache layer, rate limiting and circuit breakers so the database is never asked for more than it can serve, and a replicated Redis setup so one node is not a single point of failure.

Why this works

Scale is the whole distinction, so say the number out loud: many keys, or the whole cache. Credit comes first from the cause you can prevent, a batch of keys written with the same TTL, and then from jitter as the direct fix. Adding a limit on how much traffic reaches the database shows you also plan for the case where prevention fails. If you can explain penetration, breakdown, and avalanche in three separate sentences, this group of questions is finished.

Model answer

Once you add a cache you cannot have strong consistency, so the goal is a short window of staleness. Under the rule is: write the database first, then delete the cache key. Delete rather than update, because two concurrent writers can otherwise leave the older value in the cache. A race still remains: a reader that loaded the old value before the write can put it back after the delete. A delayed double delete makes that window smaller but does not close it, and a short limits how long any stale value can survive. If the data cannot tolerate that window at all, the honest answer is not to cache it.

Why this works

This question is about whether you will overclaim. Never say the cache and the database are consistent; describe the window in which they disagree and how long it lasts. Credit comes from two things: write the database first and delete the key, and the reason delete beats update. Then admit the race that remains, because a slow reader can write the old value back after the delete and a delayed double delete only narrows that window. If they want more, mention invalidating from the database change log, for example a tool such as Canal reading the MySQL binlog, with a short TTL as a backstop.

Model answer

Redis executes commands one at a time on a . That is a design choice: with one thread there are no locks and no context switching between commands, and because the data is in memory each command finishes quickly. Redis 6 added extra threads, but only for network I/O — reading and writing sockets and parsing the protocol. Command execution is still serialized on one thread, which is why every command is still and why data operations still need no locking. So the accurate sentence is that command execution is single-threaded, not that Redis is single-threaded.

Why this works

The question contains its own trap, because for Redis 6 and later the phrase single-threaded is not accurate. Credit comes from separating the two layers: I/O threads read and parse, one thread executes. Present the single execution thread as a benefit, no locks and no context switching, rather than a limitation nobody has fixed yet. The opposite trap matters too: do not say Redis 6 runs commands in parallel, because it does not.

Take these four

Summary · remember this

  • 1 is a speed layer, not the . It can become unavailable at any time, so every usage needs a fallback or a way to recompute from the original source.
  • 2 in four beats: check the cache → (hit) return it / (miss) read the source → write it back with a .
  • 3Remember the three WeShipItNow usages: rate cache (a read cache), label (a concurrency guard), and balance (a read model).
  • 4The honesty rule: every word on your resume has to survive follow-up questions. Do not claim work you did not do, and do not invent numbers, such as that 40%, that you never measured.
Cache-aside · four beats
① Check cacheGET key
② Hit? return itcache hit
③ Miss? read sourceDB / carrier API
④ Write back + TTLSET key … EX
↻ Back to Stop 1