Write Amplification
One logical write producing many physical writes - through fan-out, indexes, replication or storage-engine mechanics - and why it decides scaling limits.
Write amplification is the ratio between what the application asked for and what the system actually wrote. It appears at several independent layers, and the total is their product rather than their sum, which is why it surprises people.
At the application layer. One publish written into every follower's timeline. One order updating inventory, ledger, search index and analytics.
At the index layer. A row insert also writes every index on the table. Ten indexes means eleven writes, which is why unused indexes are not free.
At the replication layer. Every write is written again on each replica, and again in each region.
At the storage-engine layer. Log-structured merge trees rewrite data during compaction; the same record may be written several times over its life. B-trees write whole pages for small changes and write ahead to a log first.
Why it matters
Write capacity is usually the hard ceiling in a data architecture — reads scale with replicas and caches, writes do not. Amplification determines where that ceiling sits, and it is frequently the actual reason a system "needs sharding" when the logical write rate looks modest.
It is also the mechanism behind a specific class of incident: a single logical event producing a burst large enough to saturate the write path for everyone else.
Implementation patterns
- Bound the fan-out. Hybrid fan-out — push for ordinary publishers, pull for very high-follower ones — is the standard defence against the celebrity case, where one action produces tens of millions of writes.
- Audit indexes. Remove indexes with no query using them; each one taxes every write forever.
- Batch and coalesce. Aggregate counter updates in memory and flush periodically, turning thousands of writes on one row into one write per interval.
- Write asynchronously where the derived data tolerates it, so amplification lands on a background path with its own capacity rather than on the user's request.
- Skip inactive recipients. In feed fan-out, a large fraction of followers have not opened the product in months; materialising for them is pure waste, and lazy materialisation removes it.
- Choose the storage engine for the write pattern. LSM engines suit append-heavy workloads; B-trees suit read-heavy ones with in-place updates.
Industry example
The celebrity fan-out problem is the clearest case. A platform materialises timelines on write, which is correct for the overwhelming majority of accounts: one publish, a few hundred writes, and reads become a single sequential lookup.
Then an account with tens of millions of followers posts. One user action becomes tens of millions of writes arriving as a burst, saturating the write path and delaying timeline updates for every other user on the platform. Nothing failed; the design simply encountered the tail of its own distribution.
The same shape appears in a message to an enormous community channel, in a notification triggered for millions of users after a major event, and in an inventory update that cascades into search, pricing, recommendations and analytics.
The resolution is always to make the amplification a function of something bounded: publish once and pull at read time for the extreme cases, prioritise active recipients, and let the long tail complete asynchronously over minutes.
Failure scenarios
- Unbounded fan-out with no classification, so a single event is an incident.
- Index sprawl discovered only when write latency degrades, long after the indexes were added.
- Synchronous derived writes on the request path, so the user waits for the analytics update.
- Retry of a partially completed fan-out, re-sending to recipients who already received it — which requires idempotent per-recipient writes.
- Compaction storms, where deferred storage-engine amplification arrives all at once and stalls reads.
Trade-offs
Reducing write amplification usually means accepting read amplification: pull-based feeds make writes cheap and reads expensive; removing an index makes writes faster and one query slower; asynchronous derived writes make the request fast and the derived data stale.
The judgement is which side of the ratio has headroom. Read amplification can be absorbed by caches and replicas, which are cheap and horizontally scalable. Write amplification lands on the primary, which is the resource that is hardest to scale — which is why, when in doubt, the trade usually runs toward protecting writes.
Interview question
"An account with 40 million followers posts. Walk me through every layer of write amplification that one action triggers, and tell me which layer you would attack first."