The Write Path
LSM-tree vs B-tree storage engines, measured
The measured result

The copy-on-write B-tree wrote 44× its logical data; the LSM-tree only 2.5× - while the LSM-tree still took writes about 11× faster. Write amplification is regime-dependent, not a fixed property of the design.
11×
faster writes (LSM)
17×
faster reads (B-tree)
100%
reproducible (Docker)
What's inside
- The write path traced step by step through a B-tree (PostgreSQL-style) and an LSM-tree (RocksDB-style).
- The three amplifications - write, read, space - and the RUM trade-off that couples them.
- A measured comparison with a reproducible Docker harness, not hand-waved numbers.
- A workload-driven framework for choosing an engine, with four worked archetypes.
- A benchmarking protocol that avoids the common ways such tests mislead.
- Full references to the primary literature and vendor docs.
Table of contents
- Preface
Preface
Introduces the book's premise that a database's decision to update data in place or append it elsewhere shapes nearly everything measurable about it, states that the book follows one write path through the B-tree and LSM-tree rather than surveying many systems, and explains that all benchmark figures come from the included harness rather than estimates.
- Chapter 1
Two Philosophies of Writing
Lays out the update-in-place (B-tree) and out-of-place (LSM-tree) philosophies, the structure they share (sorted key-value stores, write-ahead logs, in-memory caching), and previews a comparison table of trade-offs that later chapters justify in detail.
- Chapter 2
Inside the B-Tree Write Path
Walks a single UPDATE through PostgreSQL's B-tree write path - locating and latching the page, writing the WAL, deferring the dirty-page write, and checkpointing - then explains where write amplification comes from (page granularity, the WAL, full-page writes) and how settings like fillfactor and checkpoint spacing tune it.
- Chapter 3
Inside the LSM-Tree Write Path
Follows a write through RocksDB's LSM-tree, where WAL append and MemTable insert are the only synchronous steps, then covers flushing to SSTables, leveled versus size-tiered compaction, and the write-stall backpressure mechanism triggered when compaction can't keep pace with ingestion.
- Chapter 4
The Three Amplifications
Defines write, read, and space amplification and the RUM conjecture, then reports the book's own measured benchmark comparing Pebble (LSM) and bbolt (B-tree) at one million keys, showing the LSM-tree faster on writes and mixed workloads, the B-tree faster on reads, and that the write-amplification ranking between the two designs is regime-dependent rather than fixed.
- Chapter 5
Choosing an Engine
Turns the analysis into a decision framework built around how write-dominated a workload is, what shape its reads take, and tie-breaker factors like SSD endurance, space budget, and tail latency, applying it to four representative workloads and noting that many systems reasonably run both engine types side by side.
- Chapter 6
Conclusion: Measure Your Own Write Path
Restates the RUM trade-off as the book's central idea and gives a six-step protocol for benchmarking your own workload - replaying real traffic, sizing data beyond memory, running long enough to trigger compaction and checkpoints, measuring bytes-to-device, and reporting tail latency - instead of relying on published numbers.
Who this is for
- Backend developers who need to select a datastore for a new system
- Database administrators tuning an existing B-tree or LSM-tree deployment
- Architects who need to defend a storage-engine decision with evidence rather than opinion
- Engineers who want to reason about which engine fits a given workload instead of following rules of thumb
The book assumes a working engineer with familiarity with the general idea of a B-tree and with solid-state storage; where theory is required, it is built up from first principles.
How this was measured
The benchmark uses a single Go harness (in the bench/ directory, run via Docker) that drives an identical workload through two production embedded engines - Pebble, the LSM-tree behind CockroachDB, and bbolt, the copy-on-write B+-tree behind etcd - so the data structure is the only variable, with Pebble's compression disabled for a purely structural comparison. It ran on an AMD Ryzen 7 5700X (8 cores/16 threads) with roughly 11.6 GiB given to Docker Desktop 29.5.3 (Linux containers, WSL2-backed storage), inserting 1,000,000 keys (16-byte keys, 100-byte values, uniform-random order, fixed seed 42) across three phases: a batched, fsync-per-batch fill, random-read lookups, and a 50/50 mixed phase with no per-op fsync. Throughput, write amplification (device write_bytes from /proc/self/io during fill divided by logical bytes), and space amplification (on-disk size divided by live-data size) are all measured directly by the harness, not estimated; only a handful of claims - the original 1996 LSM-tree paper's observation about B-tree insert cost, WiscKey's reported 50x amplification at scale, and the RUM conjecture itself - are cited from external sources rather than measured in this run.
From the preface
Every database makes one decision before any other: what happens, physically, when a row is written. The choice is whether to overwrite the data in place or to append it elsewhere and reconcile the result later. That decision propagates into most of what can be measured about the system, including write throughput, read latency, space overhead, how hard the underlying solid-state drive works, behaviour under a sudden load spike, and ultimately the cost of the hardware.
Frequently asked
What exactly does the benchmark measure?
It runs an identical Go workload through two production embedded engines, Pebble (the LSM-tree behind CockroachDB) and bbolt (the copy-on-write B+-tree behind etcd), across fill, read, and mixed phases on one million 16-byte-key/100-byte-value entries, and computes write amplification from bytes written to the block device (via /proc/self/io) divided by logical bytes, plus space amplification from on-disk size divided by live-data size.
Do I need to run the harness myself?
No, but the book is built around the idea that you should - the harness lives in the bench/ directory, runs via Docker (docker build -t writepath-bench bench/, then docker run), and the conclusion lays out a six-step protocol for benchmarking your own workload rather than trusting the published numbers as-is.
Is this beginner-friendly?
The preface states it assumes "a working engineer" who already has familiarity with the general idea of a B-tree and with solid-state storage, though it builds up theory from first principles where needed - so it is not a from-zero introduction to databases, but it doesn't require prior storage-engine expertise either.
Which real databases does the book use as examples?
PostgreSQL illustrates the B-tree write path (Chapter 2) and RocksDB illustrates the LSM-tree write path (Chapter 3) in the prose. The actual measured benchmark, however, uses two embedded engines, Pebble and bbolt, because comparing a full SQL server against an embedded key-value library head-to-head would not be apples-to-apples.
Does the book just tell me which engine to pick?
It provides a decision framework (Chapter 5) built on three questions - how write-dominated the workload is, what shape its reads take (point lookups versus range scans), and tie-breakers like SSD endurance and space budget - applied to four example workloads (time-series ingest, classic OLTP, event logs, embedded key-value caches), rather than declaring one engine universally superior.
Will the benchmark numbers in the book match my own hardware?
No, and the book says so directly: the appendix and bench README note the figures come from one desktop workstation (AMD Ryzen 7 5700X, Docker Desktop on WSL2-backed storage), not a tuned server, that absolute throughput depends on hardware, scale, and configuration, and that the numbers were taken right after a bulk load before compaction fully settled - the intended use is to read the ratios and crossover, then reproduce the harness on your own workload.
Convinced? Get the full book.