> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Routing and the Celebrity Problem

> Explains routing layer placement and strategies to handle hot shards and celebrity-driven hotspots, including dedicated shards, caching, salting, and re-sharding trade-offs.

When a request arrives, some component must take the user ID, hash it, determine which shard owns that user's data, and forward the request there. That component is the routing layer.

The routing layer's single responsibility is to forward requests to the correct shard. You can place the routing layer in one of three places:

* Inside each application service (embedded routing).
* As a separate program that sits between the app and the shards (a proxy/router).
* Inside the database itself (database-side routing).

Each placement has trade-offs. The table below summarizes them for quick reference.

| Placement | Pros | Cons |
| - | -: | - |
| Inside application services | Lowest latency; no extra network hop | Routing logic duplicated across services; updating rules requires coordinated deploys |
| Separate proxy/router | Centralized routing rule; single place to change sharding config | Extra network hop; possible proxy bottleneck (mitigated by running multiple instances behind a load balancer) |
| Database-side routing | Simplest for app developers; database manages routing | Less control over routing semantics; you must accept DB-provided behavior |

1. Routing inside application services\
   Each microservice contains the routing logic so it can contact the correct shard directly. For example, the profile service receives Chris's request, computes that user ID 41 hashes to shard 3, and connects straight to shard 3. This is the most direct path and gives the lowest latency since there’s no extra hop.

However, the routing logic is duplicated across services. If you change the sharding rule (for example, from 4 shards to 5), every service must be updated. If even one service (say, the likes service) still uses the old rule, it will route users to the wrong shards and cause incorrect reads/writes.

![A dark-themed diagram of an app server showing Profile, Feed, and Likes components receiving a user's action. It illustrates hashing/modulo sharding across five database shards and a failed write to shard 3.](https://mintcdn.com/kodekloud-c4ac6d9a/U9fTv2NKZBAqmNMH/images/System-Design-Database-Sharding/Routing-and-Hot-Shards/Routing-and-the-Celebrity-Problem/appserver-modulo-sharding-five-shard3-failure.jpg?fit=max\&auto=format\&n=U9fTv2NKZBAqmNMH\&q=85\&s=bb67f6e1ed0f32de877abeca4e3c4b98)

If services are not updated in lockstep after a sharding rule change, routing mismatches can cause serious consistency and availability problems. Coordinate deploys and use feature flags or a central configuration source to reduce risk.

2. Routing as a separate proxy\
   An alternative is a dedicated router that sits between services and shards. All services send requests to this proxy, and the proxy computes the target shard.

Example flow:

```text theme={null}
user_id 41 -> HASH ÷ 4 -> 3
```

This is how systems like [MongoDB](https://www.mongodb.com/docs/manual/core/sharding/) operate: a router (for example, [mongos](https://www.mongodb.com/docs/manual/reference/program/mongos/)) fronts the shards. Because the routing rule is centralized, changing the sharding configuration requires updating only the proxy.

Downsides are the extra network hop (slightly higher latency) and the possibility of the proxy becoming a bottleneck. To mitigate this, run multiple router instances behind a load balancer and design for failover.

3. Routing on the database side\
   You can let the database handle routing. Any shard can receive a request and forward it to the shard that holds the data. This minimizes work for application developers, but you lose some flexibility because routing behavior is governed by the database.

Whichever placement you choose, the routing layer performs the same job: send each request to the shard that contains the requested data.

Now a common question arises: if users are evenly divided across shards, how can one shard become overloaded?

![A stylized diagram titled "Users Divided Evenly" showing a user (Chris) sending a request through an app to a routing layer that hashes the user\_id and takes remainder ÷4. The routing layer evenly directs traffic to four database shards labeled Shard 0–3.](https://mintcdn.com/kodekloud-c4ac6d9a/U9fTv2NKZBAqmNMH/images/System-Design-Database-Sharding/Routing-and-Hot-Shards/Routing-and-the-Celebrity-Problem/users-hash-mod4-shards.jpg?fit=max\&auto=format\&n=U9fTv2NKZBAqmNMH\&q=85\&s=c7fa508af012d72d3804f2d8a47af672)

Hotspots and the celebrity problem\
Consider Lena, a pop star with 40 million followers. Suppose Lena's user ID hashes to shard 2. Each shard has an approximate capacity (for example, 100,000 reads per second). When Lena posts, millions of her followers may try to read that post, concentrating massive read traffic on shard 2. Meanwhile shards 0, 1, and 3 might only be handling \~20,000 reads/sec each. Shard 2 becomes overwhelmed, and everyone whose data lives on shard 2 experiences degraded performance.

This concentrated overload on a single shard is called a hotspot. When caused by an extremely popular user, it’s commonly called the celebrity problem.

There are three common mitigation techniques; teams often combine them.

1. Move the hot user to a dedicated shard (directory-based exception)\
   One pragmatic approach is to give Lena her own shard. Practically, the routing layer contains a directory mapping Lena's user ID to a dedicated shard. At routing time the router checks the directory first.

Example routing directory concept:

```text theme={null}
USER_ID  SHARD
500      4

USER_ID -> HASH ÷ 4 -> REMAINDER
```

If the request concerns Lena (user\_id 500 in this example), the router forwards it to shard 4. Otherwise, it applies the normal hash-based routing. This isolates Lena's profile and posts, but the dedicated shard still has finite capacity (e.g., \~100k reads/sec).

![A schematic diagram of a hash-based sharding system showing user "Lena" (user\_id 500) looked up in a routing directory and mapped to shard 4. Shard 4 is highlighted as holding Lena's data and handling \~100K reads/sec while other shards are shown in the cluster.](https://mintcdn.com/kodekloud-c4ac6d9a/U9fTv2NKZBAqmNMH/images/System-Design-Database-Sharding/Routing-and-Hot-Shards/Routing-and-the-Celebrity-Problem/hash-sharding-lena-user500-shard4-100k.jpg?fit=max\&auto=format\&n=U9fTv2NKZBAqmNMH\&q=85\&s=ce67b307ba4db56d7834e7c125c0ccf1)

2. Use a read cache\
   Most hotspot traffic is reads. A cache (CDN, edge cache, or in-memory cache) can absorb the majority of read requests so they never hit the shard. Remember: caches only help reads — writes must still reach the datastore.

3. Spread writes using salting (shard key diversification)\
   Large-scale applications often duplicate writes to satisfy different access patterns. For example, when Chris likes Lena's post, one copy of that like might be stored with Chris's data (so Chris’s activity is preserved on his shard) and another copy stored with the post (so the like count and followers-of-the-post are local to the post's shard). Without these patterns, millions of likes would concentrate write traffic on the shard that stores Lena’s post.

To distribute write load for a hot key, use salting. Instead of storing every like under a single key (e.g., `500`), create multiple salted keys like `500-1`, `500-2`, …, `500-10`. Each new like is written under one salted key (commonly chosen at random). Because even a small change to the shard key drastically changes the hash result, salted keys are likely to hash to different shards. Note that salted keys map onto existing shards — you’re not adding machines — but likes will be spread across shards rather than all landing on shard 4.

The trade-off is that computing an aggregate (like total like count) now requires reading all 10 salted keys from potentially different shards and summing them. Therefore salting is applied selectively, only to the hottest keys.

The routing layer keeps a list of which keys are salted so it knows whether to write to a single salted key (for an individual like) or to read multiple salted keys (for an aggregate view).

Salting reduces per-shard write pressure at the cost of more complex reads (you must aggregate across salted keys). Use it only for very hot keys and track salted keys in the routing metadata.

How the routing layer decides (summary)\
Every read first goes to the cache; if the cache has the answer, the response is returned immediately and the routing layer is not involved. If the cache misses, or the request is a write, the request reaches the routing layer. The routing layer then evaluates:

1. Is this request about likes on Lena's post?
   * If yes (a like write), pick one of the salted keys at random and send the write to the shard responsible for that salted key.
   * If yes (a like read for total count), read all salted keys and sum the results.

2. Is this any other request for Lena (for example, opening her profile or reading her posts)?
   * If yes, route directly to Lena's dedicated shard (shard 4 in the example).

If neither question applies, the request is for a normal user (e.g., Chris). The router applies the normal hash-and-modulo rule to pick the correct shard and forwards the request.

![A diagram titled "How routing decides" showing an app sending requests through a cache to a routing layer that salts keys and uses a hash + remainder (modulo) on user\_id to pick a database shard. The graphic illustrates salted key examples and arrows distributing traffic to multiple shards (Shard 0–4).](https://mintcdn.com/kodekloud-c4ac6d9a/U9fTv2NKZBAqmNMH/images/System-Design-Database-Sharding/Routing-and-Hot-Shards/Routing-and-the-Celebrity-Problem/routing-salt-hash-modulo-userid-shards.jpg?fit=max\&auto=format\&n=U9fTv2NKZBAqmNMH\&q=85\&s=4aa2c9a55dd0f5c3039fde36d22788aa)

Re-sharding as the user base grows\
As the user base grows, normal users like Chris and Leo increase in number until all shards start to fill. The typical response is to add more shards and change the hashing rule (for example, divide by the new number of shards instead of 4). But changing the shard count changes the hash-to-shard mapping for existing data, so many records must move.

For example, suppose the hash for Chris is 4,821,371. With 4 shards:

```text theme={null}
4,821,371 ÷ 4 -> remainder 3  => Chris on shard 3
```

With 5 shards:

```text theme={null}
4,821,371 ÷ 5 -> remainder 1  => Chris now belongs on shard 1
```

That means Chris's data must move from shard 3 to shard 1, even though Chris's ID and data didn't change.

![A stylized diagram illustrating database sharding with an app and users on the left and five data shards on the right. The routing layer computes "Chris's hash 4,821,371 ÷ 5 → 1" and directs Chris's data to shard 1 (highlighted).](https://mintcdn.com/kodekloud-c4ac6d9a/U9fTv2NKZBAqmNMH/images/System-Design-Database-Sharding/Routing-and-Hot-Shards/Routing-and-the-Celebrity-Problem/database-sharding-chris-shard-1.jpg?fit=max\&auto=format\&n=U9fTv2NKZBAqmNMH\&q=85\&s=538a57690414e70daea3e1c39c45634a)

So how can we add a new shard without moving almost all the data?

> **[Watch Video](https://learn.kodekloud.com/user/courses/database-sharding/module/70542938-eec7-4d5f-afbc-9f3fd10906d9/lesson/b820ce2c-1ce9-4648-b8c3-2c3fb7616798)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.