Close-up of weathered hands laying a new brick on top of a partially built brick wall, warm light glowing in the background Tech
AI-generated, Working Theory
Tech · ◉ Evergreen

The trick to fast writes is to stop updating in place.

by · ·4 min·Working Theory

A plain-English tour of the log-structured merge tree — why the fastest way to write data is to never go back and edit it, and what you pay for that speed later.

Here’s a puzzle that trips up a lot of people the first time they meet it. A database that stores your data on a spinning or flash disk has to do two things that pull in opposite directions: write new data quickly, and find old data quickly. The classic design — the B-tree, the thing under most traditional databases — is organized for finding. It keeps everything sorted in place, so a lookup is a few confident hops. But that sorted-in-place order is exactly what makes writing slow: to insert one new record in the right spot, you often have to go edit a page sitting at some random location on disk, and random edits are the slowest thing storage does.

So a different family of storage engines — the one under RocksDB, LevelDB, Cassandra, and a lot of what you’re using without knowing it — makes the opposite trade. It is built around a simple refusal: never update data in place. Only ever append.

How that actually works

When a write comes in, it doesn’t go hunt for the record’s home on disk. It does two cheap things: it appends the change to a log file (so nothing is lost if the power dies — the same durability trick a write-ahead log gives you), and it drops the new value into a sorted table held in memory. Memory is fast and the log is a pure append, so the write returns almost immediately. No seeking, no editing a page in place.

That in-memory table fills up. When it does, the engine writes it out to disk in one go as an immutable, sorted file — and then leaves it alone forever. It never edits that file. More writes arrive, fill a new in-memory table, and get flushed to a new file beside the old one. Over time you accumulate a stack of these sorted files, newest on top.

write in-memory table + append-only log flush when full disk small sorted files compaction: merge & drop old versions one larger sorted file reads check memory first, then newest file down
Writes append to memory and a log; full tables flush to immutable sorted files; background compaction merges the pile back down. Original diagram · Working Theory

Where the bill comes due

Nothing is free, and the appender’s bill arrives at read time. To read a key, the engine checks the in-memory table first, then the newest file on disk, then the next, working down until it finds the value — because a newer file might hold an updated version of a key an older file still has. Left unchecked, that pile would grow forever and every read would get slower. Two things save it. First, each file carries a compact in-memory summary (a Bloom filter) that can say “this key is definitely not in me” cheaply, so most files get skipped without being touched. Second, a background job called compaction quietly merges the small files into larger sorted ones, throwing away superseded values and deleted keys as it goes — which is also, incidentally, how a “delete” actually happens: you append a little tombstone marker now, and the data is really dropped later, during a merge.

So the whole design is one trade stated honestly: writing is fast because you never go back and fix anything; reading and disk cost stay bounded because a background process goes back and fixes everything, later, in bulk. You moved the expensive, in-place work off the critical path and batched it. That’s the same instinct behind a lot of good engineering — and a lot of good product decisions, come to think of it: don’t make the user wait on cleanup that can happen after they’ve moved on.

The one thing worth internalizing if you build on top of these engines: a sudden write spike doesn’t just cost you at write time. It schedules compaction work that lands on the system minutes later, competing for the same disk your reads need. The speed was borrowed. Compaction is when you pay it back.

Sources

  • the log-structured merge tree (O'Neil, Cheng, Gawlick & O'Neil, 1996)
  • SSTables and memtables (Google Bigtable, LevelDB)
  • Bloom filters (Burton Bloom, 1970)
  • the RUM conjecture (Athanassoulis et al., 2016)

Liked this? Get the next one in Working Theory.

Going weekly in August (it's in beta now). One genuinely interesting read on building, the brain, and the science most people missed.

Subscribe →
Got a reaction, a counter-example, or something I missed? Reply by email — I read everything.
◉ join in

Where have you hit this — in a product you use, or one you're building?

Threads open here soon. For now, the conversation lives two clicks away — discuss on GitHub, or just reply by email. I read and answer everything.