Knowledge Guide
HomeSystem DesignData Partitioning

hard Request Routing & Partition Discovery

Partitioning splits the data; routing has to know where the pieces went

Once a dataset is split into partitions spread across N nodes, a request for key K is only correct if it reaches the one node (or replica set) that currently owns K’s partition — ask the wrong node and you get, at best, an extra hop, at worst a miss on data that is actually there. So partitioning is never complete on its own; it always ships with a second mechanism, request routing, whose only job is answering “who owns K right now?” and keeping that answer current as the cluster reshapes itself. Every partitioned system — Redis Cluster, Cassandra, Vitess/MySQL sharding, Kafka — picks one of exactly three places to put that answer.

Three places to put the key → node map

  1. Routing tier (proxy). A dedicated, partition-aware layer sits in front of the cluster, holds the map, and forwards every request to the right node. The client just talks to the router as if it were the whole database and carries zero partitioning logic. Vitess’s VTGate and a Redis-fronting proxy (twemproxy, Envoy with a Redis filter) both work this way.
  2. Node-forward (ask any node). Clients connect to any node in the cluster. If that node owns K it answers directly; if not, it redirects the client (or itself forwards internally). Redis Cluster’s MOVED/ASK replies and Cassandra’s any-node-can-coordinate model both work this way — every node holds the full map, so any entry point routes correctly, at the price of an extra hop on a miss.
  3. Partition-aware (smart) client. The client itself holds the key → node map and connects straight to the owner — no intermediary, fewest possible hops. Cassandra’s token-aware drivers, Kafka producers (which cache the partition-leader map), and sharded-driver setups that skip a proxy layer all behave this way. The cost simply moves into the client: it must fetch the map and keep it from going stale.
Three columns showing the same node layout: 1) routing tier, client to router to N2; 2) node-forward, client to N0 which redirects MOVED to N2; 3) smart client, client holds the map and connects straight to N2. A footer notes all three need a fresh key-to-node map after rebalancing.
Three columns showing the same node layout: 1) routing tier, client to router to N2; 2) node-forward, client to N0 which redirects MOVED to N2; 3) smart client, client holds the map and connects straight to N2. A footer notes all three need a fresh key-to-node map after rebalancing.

The one problem all three share: the map changes

Wherever the map lives — router, every node, or every client — it is only a cached fact, and rebalancing invalidates it: a node joins, a node leaves, or a partition is split or moved, and the old answer for K becomes wrong. The routing tier concentrates that update problem in one process; node-forward and smart-client push the identical update out to N nodes or M clients, so *how the update propagates* matters as much as *what the map says*. Two mechanisms dominate in practice:

Traced: a client mid-flight during a rebalance

Key K=42 is owned by N2. An operator triggers a rebalance that moves its partition to N4. Two clients are in flight: one refreshes its map immediately, one is still holding the old answer.

stepeventmap saysrequest lands on
1lookup for K=42, before rebalanceN2N2 — correct
2rebalance starts: N2 ships the partition to N4N2 (not yet updated)N2 — still correct, data hasn’t moved yet
3coordinator writes the new map; watches/gossip start propagatingfast watcher: N4 · slow watcher: N2depends which watcher answered the client
4stale client (map still says N2) sends the requestN2 (stale)N2 replies MOVED → N4 — one wasted hop
5client updates its map from the redirect, retriesN4N4 — correct

Step 4 is the whole mechanism in miniature: a redirect isn’t a failure, it’s the system correcting a stale map on the fly — the true failure mode is a router/node that doesn’t redirect and silently serves the wrong answer (or errors) instead.

Five-step timeline: 1 lookup returns N2, 2 rebalance starts moving the partition to N4, 3 the coordinator's watch fires for some watchers before others, 4 a client with a stale map sends to N2 and gets a MOVED redirect, 5 the client updates its map and succeeds against N4.
Five-step timeline: 1 lookup returns N2, 2 rebalance starts moving the partition to N4, 3 the coordinator's watch fires for some watchers before others, 4 a client with a stale map sends to N2 and gets a MOVED redirect, 5 the client updates its map and succeeds against N4.

Pitfalls

Selection & trade-offs — how a senior engineer decides

Routing tier vs node-forward. Choose a routing tier when you want dumb, portable clients (any language, no driver logic) and can afford to run and scale one more tier — Vitess does this because MySQL clients speak the wire protocol unchanged. Choose node-forward when you’d rather not operate an extra service and can tolerate an occasional redirect hop — Redis Cluster picked this specifically to keep the deployment topology flat (just Redis nodes, no proxy fleet). You gain operational simplicity; you pay in worst-case latency on a miss and in every node needing the full map.

Node-forward vs smart client. A smart client gets the fewest hops of the three — it goes straight to the owner almost all the time — but it embeds partitioning logic in every client and every language binding, and it is the one place staleness is hardest to police, since you don’t control when a given client refreshes. Use it when clients are few, trusted, and share one well-maintained driver (Cassandra’s official drivers); avoid it when clients are many, thin, or third-party, where a routing tier or node-forward keeps the routing logic in one place you actually control.

ZooKeeper/etcd watch vs gossip for freshness. A coordination service gives near-immediate, strongly-consistent propagation at the cost of running (and depending on) a separate consensus system — worth it when misroutes must be rare and the cluster is small-to-medium (hundreds of nodes, Kafka-scale). Gossip needs no separate service and scales to very large, geographically spread clusters, but accepts an eventually-consistent view of the ring and a real convergence window — Dynamo-style stores choose this because they already accept eventual consistency elsewhere (see the Consistency Spectrum) and prioritize not having a single coordination dependency.

Takeaways


Re-authored for this guide; both diagrams hand-authored as SVG. Sources: Martin Kleppmann, Designing Data-Intensive Applications, ch. 6 (“Request Routing”); Redis Cluster Specification (MOVED/ASK); Vitess documentation (VTGate); Apache Cassandra documentation (token-aware drivers, gossip protocol); Apache Kafka documentation (partition leadership & metadata refresh). See also: Consistent Hashing, Online Resharding & Cross-Shard Operations, The Consistency Spectrum.

🤖 Don't fully get this? Learn it with Claude

Stuck on Request Routing & Partition Discovery? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Request Routing & Partition Discovery** (System Design) and want to truly understand it. Explain Request Routing & Partition Discovery from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Request Routing & Partition Discovery** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Request Routing & Partition Discovery** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Request Routing & Partition Discovery** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes