TRT
Sign in
mediumFoundationsdesign

Design a distributed caching tier for 10 million QPS. Explain how Virtual-Node Consistent Hashing avoids rehashing storms, and compare 3 ways to prevent Cache.

Walk through the $2^{32}$ hash ring with virtual nodes, the Cache-Aside stale-set race and Lease fix, and client-side L1 micro-caching (1–2s TTL) or key-salting (`key#0 .. key#9`) for single-key hot spots.

TRT practice prompt — not a verified question from a named employer.

The Runtime Theory Team2 min read

A strong answer

A strong candidate frames Design a distributed caching tier for 10 million QPS. Explain how Virtual-Node Consistent Hashing avoids rehashing storms, and compare 3 ways to prevent Cache. around the exact memory layout, compiler semantics, and hardware execution model covered in [Virtual-Node Consistent Hashing Rings and Cache Stampede Protection (Singleflight & Leases)]. Walk through the $2^(32)$ hash ring with virtual nodes, the Cache-Aside stale-set race and Lease fix, and client-side L1 micro-caching (1–2s TTL) or key-salting (key#0 .. key#9) for single-key hot spots.

Your cluster caches 50 million product profiles across $M = 10$ Redis shards using shard = hash(key) % 10. When 1 Redis shard crashes (or you scale to 11 shards), hash(key) % 9 changes for 90% of all keys simultaneously! Even worse, when a celebrity product's cache key expires at midnight while 20,000 users are viewing it, all 20,000 requests miss Redis at the exact same millisecond and fire 20,000 identical SQL queries at PostgreSQL—crashing the primary database (Cache Stampede / Thundering Herd)!

When engineers encounter this bottleneck in production, a surface-level API description rarely explains what went wrong. In real workloads, every line of code executes against concrete hardware constraints: fixed-width memory cells, CPU cache lines, kernel descriptor tables, network socket buffers, or accelerator memory buses. Without a clear mental model of Consistent Hashing with Virtual Nodes and Cache Stampede (Thundering Herd) Prevention, debugging degrades into guesswork—tuning timeouts, adding retries, or scaling instances blindly while the underlying architectural flaw remains untouched.

In a production interview, always connect the specification rule to its concrete runtime consequence: state what lives on the stack versus the heap or static storage segment, how the compiler or operating system validates alignments, lifetimes, and error codes, and what happens under adversarial or boundary inputs (such as zero-length buffers, integer overflow, concurrent mutation, or partial I/O). Backing your explanation with a small trace of register/memory state transitions immediately separates senior systems engineers from candidates who only memorized syntax.

What the interviewer is listening for

  • Mastery of core invariant: Implement Virtual-Node Consistent Hashing with binary search wrap-around and prove why scaling moves only $1/M$ of keys.
  • Mastery of core invariant: Eliminate Cache Stampedes (Thundering Herds) using in-process Singleflight coalescing, Soft-TTL early refresh, and TTL jitter.
  • Mastery of core invariant: Prevent the classic Cache-Aside stale-overwrite race condition using Memcache Lease Tokens or CDC log invalidation.
  • Hardware and ABI awareness: Explaining how sizes, alignments, calling conventions, or kernel boundaries behave on real 64-bit targets rather than relying on implementation-defined assumptions.
  • Defensive engineering: Naming the exact compiler flags (-Wall -Wextra -Werror), static analyzers, or runtime sanitizers (-fsanitize=address,undefined,thread) that verify correctness in CI.

Common mistakes

  • Explaining only surface syntax without tracing the underlying memory addresses, ownership lifetime, or kernel/user-space state transitions.
  • Assuming undefined behavior (such as signed overflow, uninitialized reads, strict-aliasing violations, or dangling pointers) will "just work" because it passed an unoptimized -O0 debug build.
  • Ignoring return codes, partial reads/writes, alignment padding, or cleanup paths when an allocation or syscall fails midway through a function.

This answer walks

Practice follow-ups

  1. 01Consistent Hashing distributes **distinct** keys evenly across $M$ shards, but what if **one single key** (`celebrity_post_999`) receives 2,000,000 reads/sec? Since `hash('celebrity_post_999')`.
  2. 02Why should writes in Cache-Aside **invalidate (`DELETE`)** the cache key rather than **updating (`SET`)** the cache key directly from the writer?

Not started

Sign in to save your learning progress.

Sign in to save