Concept

Why Write Scaling Is Harder Than Read Scaling

The Write Scaling Challenge

Reads are easy to distribute — spin up replicas and route SELECT traffic to them. Writes are harder because they change state. Every write must update indexes, potentially invalidate cached values, be durably persisted, and be consistently replicated. A single primary node eventually hits a ceiling on the write throughput it can sustain. Once you've exhausted vertical scaling, the only path forward is distributing writes.

Strategy 1: Sharding

Split the database into independent partitions called shards, each stored on a separate server. A shard key determines which shard a given record lives on. Each shard handles a subset of write traffic, so total write throughput scales linearly with the number of shards.

  • Use when: Write load is the confirmed bottleneck, a clear high-cardinality shard key exists, cross-shard JOINs are not required, and per-record transactional guarantees are not needed across shards.
  • Hotspots — the primary failure mode: If the shard key has low cardinality or if writes concentrate on one value (e.g., a popular user), all load flows to one shard while others sit idle. The result is worse than no sharding at all.

Strategy 2: Async Writes with Message Queues

Instead of writing directly to the database, write requests are published to a message queue (RabbitMQ, SQS, Kafka). Worker processes drain the queue and write to the database at a controlled, sustainable rate. This converts a spiky write workload into a smooth, leveled stream, protecting the database from traffic spikes.

Strategy 3: CQRS + Event Sourcing

Command Query Responsibility Segregation separates the write path from the read path. The write model accepts commands and appends events to an event log (fast, simple appends). The read model maintains one or more denormalized, query-optimized projections built by consuming events asynchronously. The two models are synchronized eventually, not immediately.

Strategy 4: LSM-Tree Databases

Cassandra, ScyllaDB, and RocksDB use Log-Structured Merge-Trees instead of B-Trees. Writes land in an in-memory buffer (memtable) and a Write-Ahead Log for durability. The memtable is periodically flushed to disk as an immutable SSTable. Background compaction merges SSTables. This architecture makes writes extremely fast (sequential memory writes, no random disk seeks) at the cost of increased read complexity.