B-Trees vs LSM-Trees

Almost every database on earth stores its data in one of two structures: a B-tree that updates in place, or an LSM-tree that only ever appends. This one choice ripples through everything — read speed, write speed, space usage, and latency predictability — so knowing which your database uses tells you more about its behavior than almost anything else.

The last post introduced the storage engine as the layer that puts rows on disk. Now we look at how — the two structures that dominate storage engines. A B-tree modifies data where it lives; an LSM-tree never modifies anything, only appends and merges. These aren’t just implementation details: they produce databases with opposite performance personalities, and understanding the trade-off is the single most useful thing you can know about a storage engine.

The B-tree: update in place

The B-tree (specifically the B+tree in most databases) is the traditional workhorse — the engine behind PostgreSQL, MySQL’s InnoDB, SQL Server, and most relational databases. It’s a balanced tree of pages, kept sorted by key:

                 ┌─────────────┐
                 │  root page  │        (keys guide the search)
                 └──────┬──────┘
            ┌───────────┼───────────┐
      ┌─────▼────┐ ┌────▼─────┐ ┌───▼──────┐   internal pages
      │  keys →  │ │  keys →  │ │  keys →  │
      └────┬─────┘ └────┬─────┘ └────┬─────┘
       ┌───▼──┐    ┌────▼──┐    ┌────▼──┐
       │ rows │ .. │ rows  │ .. │ rows  │        leaf pages (actual data)
       └──────┘    └───────┘    └───────┘

To find a key, you start at the root and follow pointers down to the leaf — a handful of page reads even for a huge table, because the tree is shallow and wide (each page holds hundreds of keys, so a tree of depth 3–4 addresses billions of rows). To change a row, the B-tree finds the leaf page and modifies it in place.

The consequences:

The B-tree’s bias is clear: it’s optimized for reads and range queries, at the cost of write-time random I/O.

The LSM-tree: only ever append

The log-structured merge tree (LSM-tree) — behind Cassandra, RocksDB, LevelDB, ScyllaDB, and many write-heavy stores — takes the opposite stance: never update in place, only append. Writes go to an in-memory sorted structure and a sequential log; the structure is periodically flushed to disk and merged in the background.

write → [ memtable ]  (in-memory, sorted)  + append to WAL
             │  (when full, flush to disk as an immutable file)
             ▼
        SSTable L0 ──┐
        SSTable L0   │  background compaction merges & sorts
        SSTable L1 ──┘  →  fewer, larger, sorted files
        SSTable L2 ...

The pieces:

Because all writes are sequential appends (memtable + log, then sequential SSTable flushes), LSM-trees achieve very high write throughput — sequential I/O is far faster than the B-tree’s random page updates.

The costs land on reads and background work:

The LSM-tree’s bias is the mirror image: optimized for writes, at the cost of read amplification and background compaction.

Write amplification, read amplification, space amplification

The two designs trade along three “amplification” axes worth naming, because they’re how you reason about the choice:

There is no free lunch: you cannot minimize all three at once, so each engine picks a point in the trade-off space. This is why two databases with identical SQL can behave completely differently under load.

Choosing (or rather, understanding what you chose)

You rarely pick a raw storage structure directly — you pick a database, and it comes with one. But knowing which you have tells you how it will behave and how to use it well:

The deeper point for this series: the storage structure is the root cause of a database’s performance character. When a database is surprisingly fast at ingest but variable on tail latency, that’s an LSM-tree talking. When it’s rock-steady on reads but you’re fighting write throughput and bloat, that’s a B-tree. The next posts — pages/buffer pool and the WAL — apply to both families, because both still work in pages and both still log ahead for durability.

Key takeaways

Further reading

Sources & References

B-tree storage in practice