Choosing the Shard Count
In one line: this is the one real tuning parameter in the design, and it is pulled in opposite directions by writes and reads. There is no universally correct value — only a value correct for a traffic profile that changes over the object's life.
The trade
As shard count increases, write throughput improves, but read latency and coordination costs rise. This creates a fundamental trade-off between write scalability and read performance.
Few shards Many shards
---------- -----------
write contention HIGH write contention LOW
read = sum 2 values read = sum 200 values
...possibly across regions
Read amplification is worse than it sounds because shards may span regions
Summing N values sounds linear and cheap. The phrase that makes it expensive is "potentially spanning nodes or regions."
Ten shards on one machine is ten local reads — microseconds. Ten shards across three regions means the read is bounded by the slowest cross-region round trip, which is tens or hundreds of milliseconds.
That is the tail-latency problem from distributed search, appearing again: a fan-out read is as slow as its slowest participant, and adding shards adds participants.
So read amplification is not really about the arithmetic of summing — it is about fan-out latency and its tail. Which is precisely why Lesson 6 does not sum on every read at all, but aggregates periodically and serves a cached total.
Estimating the count
The number of shards is determined by an estimate of near-term write traffic for a counter. For tweets this depends on follower count — tweets from users with millions of followers are assigned more shards because they are likely to receive a high volume of likes or retweets. Similarly, hashtags associated with popular or celebrity tweets may also receive sharded counters, as they can quickly trend.
'Near-term' is the operative word — this is not a permanent decision
The estimate is explicitly for near-term write traffic, not lifetime traffic. That framing is what makes the next section coherent.
A tweet's counter does not need enough shards for all the likes it will ever receive. It needs enough for the likes arriving in the next few minutes, because — as the next callout shows — that is when almost all of them arrive.
Sizing for lifetime volume would over-provision every counter for its entire quiet existence. Sizing for the near term, plus the ability to resize, is far more efficient.
Engagement is bursty and long-tailed
Tweet activity typically follows a bursty, long-tailed pattern. Engagement spikes shortly after publication and then gradually declines. As traffic patterns evolve, the initial shard allocation can become either overprovisioned or insufficient. Some counters can be consolidated to fewer shards, while others require additional shards beyond the original estimate.
Write rate over a tweet's life ### #### ##### ###### ######## ########### ################## ##############################~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ minutes ^ days, then years spike: needs many shards long tail: needs one
The shape means the right shard count changes by orders of magnitude within hours
This is the crux. A viral tweet needs hundreds of shards for the first few minutes and one for the rest of its existence.
Two consequences follow, and both are load-bearing:
A fixed shard count is wrong almost all the time. Size for the spike and you carry read amplification forever on a counter nobody writes to. Size for the tail and you fail during the only period that mattered.
The window to react is tiny. The spike arrives "shortly after publication." Any resizing mechanism that takes minutes to detect and act has already missed it — which is exactly why Lesson 2 pre-creates shards at publication rather than reacting.
So the design needs both: a reasonable upfront estimate to survive the spike, and dynamic resizing to reclaim capacity afterwards and to rescue the cases the estimate got wrong.
Note that the two mechanisms handle different errors. The upfront estimate handles predictable popularity (a celebrity). Dynamic resizing handles unpredictable popularity (an unknown going viral) and the reclamation of over-provisioned counters.
Dynamic resizing
To handle this variability, the system must dynamically increase or decrease the number of shards based on current demand.
We need to monitor write load across all shards to appropriately route requests to the appropriate shards, possibly using load balancers. Such a feedback mechanism can also help us decide when to close down some of the shards for a counter and when to add additional shards.
"What happens when a user with just a few followers has a post go viral?"
The system needs to detect such cases where a counter unexpectedly starts getting very high write traffic. We'll dynamically increase the number of shards of the affected counter to mitigate the situation.
Why a good initial estimate still matters even with dynamic resizing
"If the system can dynamically expand or shrink shard count, why is it still important to predict a reasonable initial count?"
Three reasons, and the first is decisive:
Detection takes time, and the burst does not wait. Dynamic resizing is a reactive control loop: observe load, decide, provision, route. Every step costs time, and the spike arrives within seconds of publication. A counter that starts under-sharded is already failing during the window it most needed to work.
Resizing itself is a cost during a burst. Adding shards means updating the counter-to-shard mapping and redistributing routing — a control-plane operation, executed at exactly the moment the data plane is under maximum stress.
A good estimate is nearly free. Follower count is already known. Using it costs a lookup and eliminates most of the reactive work.
The general pattern is worth naming: prediction handles the predictable, feedback handles the surprises. Relying on feedback alone means being wrong during every predictable event, and relying on prediction alone means never correcting. The Distributed Task Scheduler chapter made the same pairing with admission control and aging.
Shrinking is easier than growing, and it is worth saying why
The asymmetry is genuine and slightly counter-intuitive.
Growing must happen fast — the burst is now — and the new shards start at zero while existing shards hold accumulated values, so the routing layer must know both exist.
Shrinking has no urgency at all. Traffic has already declined, so you can take your time: stop routing writes to the shards you want to remove, wait for in-flight writes to settle, add their values into a surviving shard, and delete them. Nothing is racing you.
Shrinking is also safe to get wrong — leaving a few extra shards on a quiet counter costs a slightly more expensive read. Failing to grow during a burst costs the contention collapse from Lesson 1.
Which means the operational priority is clear: be aggressive about growing and lazy about shrinking.
Key takeaway
Shard count trades write contention against read amplification, and read amplification hurts most through fan-out tail latency when shards span regions. Engagement is bursty and long-tailed, so the right count changes by orders of magnitude within hours — meaning you need both a good upfront estimate (for predictable popularity, since detection is too slow for the spike) and dynamic resizing (for surprises and reclamation). Grow aggressively; shrink lazily.
Interview signal by level
| Level | What a strong answer sounds like |
|---|---|
| L4 | "Use more shards for popular posts." |
| L5 | States the trade: "more shards means less write contention but reads have to sum more values, so we estimate from follower count and resize dynamically if we get it wrong." |
| Staff+ | Explains why both mechanisms are needed: "engagement spikes within seconds of publication and then decays for years, so the right shard count changes by orders of magnitude within hours. Dynamic resizing alone doesn't work — it's a reactive loop, and by the time it detects the spike we've already failed during the only window that mattered. So prediction handles the predictable case and feedback handles surprises. And read amplification isn't really about summing arithmetic, it's fan-out tail latency once shards span regions." |
Next: which shard a write actually goes to.