advanced31 min studyLesson 44 in Engineering

LSM trees and compaction

Trace writes through memory and sorted runs, then reason about amplification, tombstones, and compaction debt.

On this page

What you’ll understand

  • Describe the write, flush, and merge path of an LSM storage engine.
  • Calculate physical write amplification from explicitly measured byte counts.
  • Explain why compaction scheduling and tombstone lifetime affect correctness and latency.

A feature store receives frequent updates to the same keys. Writing each update into its final sorted disk location can cause expensive small random writes. A log-structured merge tree instead accumulates updates and creates sorted immutable runs, later merging their histories. The apparent simplicity of fast incoming writes moves substantial work into compaction. An ingestion benchmark can hide unsustainable debt.

Follow one key through the write path

In a typical RocksDB path, a write is recorded in a WAL when enabled and inserted into a memory structure called a memtable. A full memtable becomes immutable and is flushed to a sorted table file. A newer value for the same key may coexist with older values in other runs. A point lookup must find the visible newest version while respecting sequence numbers, snapshots, and deletions; reading the first physical occurrence without that ordering would be incorrect.

Sorted runs support sequential construction and range scans, but several runs can overlap in key space. Bloom filters can reject many files that definitely do not contain a queried key, with possible false positives. They do not normally prove presence or return the current value. Cache and file counts change read cost. A filter tuned for point lookups may not address a workload dominated by long scans.

WA=WphysicalWlogical,Wphysical=WWAL+Wflush+Wcompaction\mathrm{WA}=\frac{W_{\mathrm{physical}}}{W_{\mathrm{logical}}},\qquad W_{\mathrm{physical}}=W_{\mathrm{WAL}}+W_{\mathrm{flush}}+W_{\mathrm{compaction}}
Write amplification is a ratio over a stated measurement interval and byte convention. This example includes WAL, flush, and compaction writes; device-internal amplification and filesystem metadata are additional if not measured.↔ Scroll wide equations horizontally.

Choose which amplification to spend

Leveled compaction organizes increasingly large levels and merges overlapping ranges; within ordinary nonzero leveled levels, sorted files are nonoverlapping in key range. Level zero can contain overlapping flush files. Other policies keep different numbers of sorted runs, changing read, write, and space amplification. There is no universal best policy independent of update rate, read mix, storage capacity, and latency objectives. Measure steady-state behavior after the dataset reaches its realistic size.

Deleting a key usually writes a tombstone rather than instantly finding and removing every old value. Compaction can discard obsolete versions only when snapshots and deeper data no longer require them. Dropping a tombstone prematurely can expose an older value that still survives in another run. Long-lived snapshots therefore affect retained history, while compaction filters and retention features require explicit application semantics. Reclaiming bytes and preserving historical reads are competing obligations, not merely cleanup preferences.

Treat compaction debt as an operating state

Incoming writes create future merge work. If the storage device spends all its bandwidth accepting flushes, debt can accumulate until file counts, read work, or space consumption force stalls. Reserve headroom for compaction and observe pending bytes, level-zero files, write stalls, and foreground latency together. Rate limiting background I/O can protect readers temporarily, but a permanently insufficient merge budget cannot be repaired by throttling alone. Compression also trades CPU time against stored bytes and bandwidth.

A fluid debt model helps separate a temporary burst from an unstable workload. Let the arrival rate mean generated compaction work, not user-request bytes, and estimate it from the chosen policy under representative updates. Completion capacity depends on the same CPU and disk resources used by queries, so it need not remain constant. Validate recovery after a write burst, and test disk space during overlapping old and new runs; the final compacted size can substantially understate the peak space requirement.

D(t)=max⁡(0,D0+(a−c)t),tdrain=D0c−a(c>a)D(t)=\max(0,D_0+(a-c)t),\qquad t_{\mathrm{drain}}=\frac{D_0}{c-a}\quad(c>a)
D is pending compaction bytes, a is generated compaction bytes/s, and c is completed bytes/s under a constant-rate approximation. These are not automatically equal to logical ingestion bytes/s.↔ Scroll wide equations horizontally.

Audit an ingestion benchmark's hidden writes

Over one steady interval an engine accepts 100 GB of logical changes, writes 100 GB of WAL, flushes 90 GB after memory overwrites, and writes 360 GB through compaction. Ignore filesystem and device-internal writes.

  1. Add observed physical writes: 100 + 90 + 360 = 550 GB. Do not add logical input again because it is the denominator, not a fourth write category.

  2. Compute write amplification as 550/100 = 5.5 under the declared accounting convention.

  3. At 20 MB/s sustained logical changes with the same mix, estimate 110 MB/s physical writes before unmeasured overhead.

  4. If the device can sustainably devote only 90 MB/s to this workload, the benchmark's logical rate is not sustainable without changing the mix, policy, or capacity.

The result

A 20 MB/s ingestion headline can conceal 110 MB/s of measured physical writing; steady-state accounting exposes the bottleneck.

Explore the model

Interactive lab

Interactive lab · queue

Observe compaction debt

Use arrival λ as generated compaction work and service μ as completed work, in equal-sized units. The fluid backlog is max(0,4+(λ−μ)t). A separate M/M/1 readout assumes Poisson arrivals and exponential service. This lab has no sorted files, tombstones, Bloom filters, or actual compaction algorithm.

Observe compaction debtFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forBackground debt must drain over time; postponing merge work does not eliminate its resource cost.

Check your understanding

Why can deleting an LSM tombstone too early make an old value visible again?

Try it yourself

A store accepts 40 GB of changes and measures 40 GB WAL, 36 GB flushes, and 124 GB compaction writes. Calculate write amplification. If compaction debt is 60 GB, generated work is 30 MB/s, and completion is 50 MB/s, estimate drain time.

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Keep logical bytes separate from the measured physical categories, and use spare compaction capacity for debt recovery.

Compare with the solution

Physical writes total 200 GB, giving amplification 200/40 = 5. With decimal units the debt is 60,000 MB and spare capacity is 20 MB/s, so ideal draining takes 3,000 seconds, or 50 minutes. Concurrent read pressure or a changed update distribution can reduce completion capacity, making the constant-rate estimate optimistic.

Take it with you

  • Immutable sorted runs move part of incoming write work into later merges.
  • Amplification numbers require explicit byte accounting and steady-state measurement.
  • Snapshot retention, deletion safety, compaction debt, and peak space interact.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.