Skip to main content
Primitives/Primitive #07
PRIMITIVE #07Core Distributed Systems Component

Write-Ahead Log (WAL) & LSM-Trees

AWS Production Mapping:DynamoDBS3AuroraOpenSearch

1. What It Is & Why It Exists

The Core Problem: The B+ Tree In-Place Update Penalty

Traditional relational database storage engines (e.g., MySQL InnoDB, Heap Storage) use B+ Trees organized into fixed-size disk pages (typically 8 KB or 16 KB). When an application updates or inserts a record:

  1. The engine traverses the B+ Tree index, loads the target page into memory (the buffer pool), and modifies the record.
  2. The dirty page is eventually written back to disk in-place at its fixed physical address.
  3. In high-velocity write workloads with random keys (such as UUIDs, user sessions, or sensor events), modifications scatter across thousands of disparate pages. Writing these pages forces the underlying storage controller to perform massive Random Disk I/O.

On modern NVMe Solid-State Drives (SSDs), random writes trigger severe write amplification due to NAND flash block-erase constraints (data must be read, erased in blocks of 2–8 MB, and re-written). On mechanical hard drives, random seeks incur a 510 ms5\text{--}10\text{ ms} mechanical penalty per operation, capping throughput at several hundred operations per second.

In contrast, Sequential Disk I/O streams data continuously, bypassing head seeks and maximizing SSD controller parallelism to achieve bus saturation (>3,500 MB/s> 3,500\text{ MB/s} on PCIe Gen 4 NVMe).

The Breakdown: The In-Place Page Rewrite Cliff

Concrete Proof: B+ Tree Random Page Rewrites vs. LSM-Tree Sequential Appends

Consider a distributed storage system ingesting 100,000 writes/second100,000\text{ writes/second} with 1 KB1\text{ KB} record payloads (100 MB/s100\text{ MB/s} raw data ingestion):

Metric / Operational DimensionB+ Tree Storage Engine (In-Place 16 KB Pages) Engine with (Sequential Append)
Disk Write Pattern🚨 Scattered Random Writes across multi-GB page poolsPure Sequential Appends to &
Physical Data Written to DiskUpdating a 1 KB record rewrites the entire 16 KB page: Physical Write=100,000×16 KB=1,600 MB/s\text{Physical Write} = 100,000 \times 16\text{ KB} = \mathbf{1,600\text{ MB/s}}Appends 1 KB record to sequential log: Physical Write105 MB/s\text{Physical Write} \approx \mathbf{105\text{ MB/s}} (with metadata)
Write Amplification (WA)🚨 WA=16×40×\text{WA} = 16\times\text{--}40\times (Page rewrites + doublewrite buffer)🛡️ WA=1.05×\text{WA} = 1.05\times at initial ingest (10×15×\approx 10\times\text{--}15\times after background compaction)
Disk Demand🚨 100,000 Random IOPS100,000\text{ Random IOPS} (Saturates storage queues)🛡️ <1,000 Sequential I/O Blocks< 1,000\text{ Sequential I/O Blocks}
Write Latency🚨 45.0 ms45.0\text{ ms} (I/O scheduler contention)0.8 ms0.8\text{ ms} (Microsecond RAM append + Group Commit)
SSD Hardware Endurance🚨 Rapid flash wear-out (Exhausts Drive Writes Per Day)🟢 Extended drive lifespan (Smooth sequential writes)

The First-Principles Solution: Append-Only LSM-Trees & WAL

The Log-Structured Merge-Tree (), designed by Patrick O'Neil et al. in 1996, resolves the random write bottleneck by converting all incoming mutations (inserts, updates, and deletes) into strictly sequential disk appends:

  1. (): The mutation is immediately appended to an append-only log on disk before being acknowledged, providing ACID Durability (DD).
  2. : Concurrently, the record is inserted into an in-memory sorted data structure (typically a Concurrent SkipList or Red-Black Tree), allowing immediate O(logN)O(\log N) search and range scans.
  3. Immutable SSTable Flush: When the reaches its capacity threshold (e.g., 64 MB), it is frozen into a read-only and flushed sequentially to disk as a sorted, immutable Sorted String Table (SSTable).
  4. Background Compaction: Background threads periodically merge overlapping , discard obsolete versions, and remove tombstoned records, maintaining logarithmic search performance.
Interactive Architecture Diagram
Synthesizing vector architecture diagram...

2. Core Mechanics & Algorithmic Architecture

The Fundamental Distributed Storage Triangle: R-W-S Amplification

Every persistent storage engine operates within the boundaries of the R-W-S Amplification Trade-off:

Write Amplification (WA)=Total Bytes Written to Physical StorageBytes Ingested by Application\text{Write Amplification (WA)} = \frac{\text{Total Bytes Written to Physical Storage}}{\text{Bytes Ingested by Application}}

Read Amplification (RA)=Total Bytes Read from Physical StorageBytes Requested by Application\text{Read Amplification (RA)} = \frac{\text{Total Bytes Read from Physical Storage}}{\text{Bytes Requested by Application}}

Space Amplification (SA)=Total Disk Space Occupied on DriveSize of Active De-duplicated Dataset\text{Space Amplification (SA)} = \frac{\text{Total Disk Space Occupied on Drive}}{\text{Size of Active De-duplicated Dataset}}

Interactive Architecture Diagram
Synthesizing vector architecture diagram...

Leveled Compaction Sizing Mathematics

In Leveled Compaction (LCS) (used by RocksDB and TiKV), disk storage is organized into discrete exponential levels (L0,L1,L2,,LmaxL_0, L_1, L_2, \dots, L_{\max}):

  • Level 0 holds flushed directly from . Because they are flushed independently, Level 0 have overlapping key ranges.
  • Levels L1L_1 and higher are strictly sorted such that no two in the same level share overlapping key ranges.
  • Each level has a maximum capacity that grows exponentially by a multiplier TT (typically T=10T = 10):

Capacity(Li)=Cbase×Ti1\text{Capacity}(L_i) = C_{\text{base}} \times T^{i - 1}

If Cbase=256 MBC_{\text{base}} = 256\text{ MB} and T=10T = 10:

  • L1=256 MBL_1 = 256\text{ MB}
  • L2=2.56 GBL_2 = 2.56\text{ GB}
  • L3=25.6 GBL_3 = 25.6\text{ GB}
  • L4=256 GBL_4 = 256\text{ GB}

The total worst-case Write Amplification in Leveled Compaction is bounded by:

WAleveledO(T×logT(DCbase))\text{WA}_{\text{leveled}} \approx O\left(T \times \log_T \left(\frac{D}{C_{\text{base}}}\right)\right)

Where DD is the total database size.


Step-by-Step Deterministic Write & Read Pipelines

Interactive Architecture Diagram
Synthesizing vector architecture diagram...

In-Memory & On-Disk State Structures

1. In-Memory SkipList Architecture

The MemTable is backed by a lock-free Concurrent SkipList. Elements are arranged in linked lists with probabilistic multi-level forward pointers, providing O(logN)O(\log N) search, insertion, and range iterations without global lock contention.

2. Immutable SSTable File Anatomy

When a MemTable flushes to disk, it produces an immutable SSTable file structured into fixed-size blocks (typically 4 KB):

Block NameFormat / ContentsPurposeMemory Location
Data BlocksCompressed key-value pairs sorted lexicographicallyHolds raw payload data (compressed via Zstandard or Snappy)Loaded into Block Cache in RAM on-demand
Filter BlockBit arrays representing for all data blocksEvaluates whether a key definitely does not exist in this SSTablePinned in RAM off-heap
Index BlockTwo-level sparse index mapping key prefixes to data block file offsetsEnables binary search to locate the exact 4 KB data block for a keyCached in RAM
Footer BlockFixed-size 48-byte trailer containing magic number and handles to Index & Meta blocksAnchor point read by storage engine when opening an SSTableLoaded on file open
Interactive Architecture Diagram
Synthesizing vector architecture diagram...

Scenario Execution Matrix: LSM Read, Write, and Compaction Dynamics

Step #Event / InputIn-Memory / Distributed StateEvaluation & TransitionOutcome / Latency &
1Point Lookup on Hot Key
GET "user_102"
Key resident in active RAM MemTable (SkipList)Binary search on concurrent SkipList locates entry; zero disk access requiredDirect RAM Hit (<40 ns< 40\text{ ns})
Returned instantly; zero checks, 0 disk
2Point Lookup on Cold Key
GET "order_4821"
Absent from MemTable; present on disk in Level 2 SSTable1. MemTable miss \to check L0 (negative, skip)
2. L1 non-overlapping index binary search (not in range)
3. L2 returns 1 \to read sparse index
Single Disk Seek (1.1 ms1.1\text{ ms})
Targeted data block read from NVMe; completely bypasses L0 and L1
3Tombstone Deletion
DELETE "user_102"
Record exists on disk across L1 and L2 Append tombstone record (0xDEADBEEF) to and MemTable;
subsequent queries return 404 immediately
Instant Tombstone Append (0.05 ms0.05\text{ ms})
Stale on-disk versions masked; during background compaction of LiLi+1L_i \to L_{i+1}, old records & tombstones permanently purged

3. Data Migration, Anti-Entropy & Consistency Protocols

1. Compaction Strategies Compared

Interactive Architecture Diagram
Synthesizing vector architecture diagram...
Compaction StrategyMechanicsWrite Amplification (WAWA)Space Amplification (SASA)Read LatencyBest Suited For
Size-Tiered (STCS)Accumulates of similar sizes; merges them into one large SSTableLow (4×8×4\times\text{--}8\times)High (100%\approx 100\% temporary disk space required)Higher (Must search multiple files per tier)Write-heavy time-series workloads ( default)
Leveled (LCS)Strictly non-overlapping key ranges per level (L1+L_1+); merges LiL_i into Li+1L_{i+1}Higher (10×30×10\times\text{--}30\times)Low (<10%15%< 10\%\text{--}15\% disk overhead)Ultra-Fast (Maximum 1 SSTable read per level)General OLTP workloads (RocksDB, TiKV, CockroachDB)
CompactionDiscards oldest SSTables once total disk quota is exceededMinimal (1×1\times)ZeroFastEphemeral in-memory caches, log aggregators

2. WAL Group Commit & Fsync Durability Protocols

Calling fsync() on a storage drive forces the mechanical or solid-state controller to flush its volatile write cache to persistent storage, capping throughput at a few hundred operations per second. Modern engines implement Group Commit:

  • Incoming client threads append their mutations to a lock-free concurrent staging buffer.
  • A single background sync worker issues fdatasync() once per micro-batch (e.g., every 1 ms1\text{ ms} or whenever 64 KB64\text{ KB} accumulates).
  • All client requests in that batch are acknowledged simultaneously, delivering 100,000+ ACID writes/second100,000+\text{ ACID writes/second} with full hardware durability.

3. Distributed Anti-Entropy, Merkle Trees & Crash Recovery

  • Merkle Tree Anti-Entropy Repair: In distributed databases (e.g., , ), node replicas detect out-of-sync data without transferring entire datasets. Replicas construct hierarchical Merkle trees over token ranges. During background anti-entropy repairs (nodetool repair), nodes exchange tree roots (O(1)O(1)) and traverse diverging child branches (O(logN)O(\log N)) to isolate diverging key ranges, streaming only the missing immutable SSTables across nodes via zero-copy network transfer.
  • WAL Checkpointing & Crash Recovery Protocol: On unexpected process termination, the engine reconstructs volatile deterministically from the on-disk :
    1. Parse the most recent Checkpoint Marker: retrieves the last flushed Log Sequence Number (LSNflush\text{LSN}_{\text{flush}}).
    2. Sequential Scan: Replay WAL log records starting strictly from LSNflush+1\text{LSN}_{\text{flush}} + 1.
    3. Tail Truncation on CRC Mismatch: Validate CRC32 checksums per record. If power loss caused a torn write at the file tail, the engine truncates the corrupted uncommitted trailing bytes up to the last valid transaction boundary, restoring consistent state.

Part 2: Production Deep-Dive Locked1 Coin = 24 Hours

Unlock Complete Architecture & Production Runbooks

Your Balance:40 Coins

You have explored the free architectural preview (~47%). Spend 1 Coin to unlock the remaining 7 production deep-dive sections for a full 24 hours.

Sections Included in This 24-Hour Pass:
4. Client-Side vs. Proxy-Mediated Routing Topologies
5. Real-World Distributed Engine Comparison
6. Critical Edge Cases & Distributed Failure Modes
7. Production Pitfalls & Anti-Patterns (The "Gotchas")
8. AWS Cloud Service Implementation & Production Patterns
9. Production Sizing Matrix & Operational Runbook
10. Production Diagnostics: Telemetry Signatures & Incident Response Playbook
Keeps page unlocked for exactly 24 hoursSpend coins to fund LLM & compute infrastructure