Designing Data-Intensive Applications
Ch. 6

Request Routing

Clients must find the right partition for each request — via routing tier, gateway, or aware clients.

Given a key, which node owns it? A routing layer answers this question. Centralized gateways are simple but can bottleneck. Smart clients avoid the hop but must handle map updates.

In practice

MongoDB mongos routers sit between apps and shards, caching the chunk map from the config servers. Kafka clients fetch partition leadership metadata from the broker controller. In Kubernetes, an nginx or Envoy ingress acts as a reverse proxy — routing HTTP/gRPC to the right pod. AWS ALB does the same at the cloud edge, with health checks and cross-AZ failover.

Twitter/X at scale

Timeline and user-data requests route through a gateway that caches the partition map. When a shard rebalances, the routing tier updates so clients always hit the node that owns a given user_id.

typescript — Gateway partition routing
// Twitter/X routing — gateway caches partition map, forwards by key
function routeRequest(userId: string, partitionMap: Map<number, string>) {
  const partition = hashPartition(userId, partitionMap.size);
  const host = partitionMap.get(partition)!;
  return proxy.forward(host, { userId }); // mongos / Envoy style
}
Key Takeaways
  • Naive approach: send all requests to a routing tier that forwards to the right node.
  • Gateway: stateless proxy that knows the partition map.
  • Partition-aware clients cache the routing table and connect directly.
  • The partition map must update when rebalancing occurs.
  • ZooKeeper, gossip protocols, or config services distribute routing metadata.
  • nginx, Envoy, AWS ALB, and MongoDB mongos are production routing layers.
request routingnginxEnvoyreverse proxymongospartition map