Konstas.Engineering Notes
Networking · Cybersecurity · Infrastructure
Systems

How Bitcoin Core Stores the Blockchain

Articles · July 2026 · Ioannis (John) Konstas

People imagine "the blockchain" as one giant database. Bitcoin Core actually uses a deliberate split: raw block data in flat files, and a fast key-value index in LevelDB. Understanding this design is a small masterclass in storage engineering — matching the storage model to the access pattern, and it explains why a full node can validate the entire chain on ordinary hardware.

Two storage models, two jobs

Flat files — the archive

The full blocks live in the blocks/ directory as sequential flat files:

Why flat files? Block data is written once and read sequentially; it's append-heavy, huge, and rarely random-accessed. A sequential file is the perfect, cheapest fit — no database overhead for data that behaves like a log.

LevelDB — the index and the UTXO set

The chainstate/ directory holds a LevelDB store containing the UTXO set (all unspent transaction outputs) and block index metadata. This is the hot data: every new transaction must check whether its inputs exist and are unspent, which demands fast random lookups and updates — exactly what a key-value store excels at and a flat file cannot provide.

Why LevelDB, specifically

LevelDB is a high-performance embedded key-value store, open-sourced in 2011. Its defining feature is the Log-Structured Merge-tree (LSM-tree): writes are batched into memory and flushed to sorted files, then merged in the background. This optimizes for fast sequential writes and fast cached reads with low memory use — a good match for Bitcoin's workload of steadily ingesting blocks and constantly querying the UTXO set. It uses Snappy compression by default, supports atomic batch updates (but not full transactions), and is single-writer, multi-reader.

A timeline that teaches a lesson

Bitcoin (2009) predates LevelDB (2011). Early Bitcoin used Berkeley DB for its indexes — and that choice caused one of the network's most instructive incidents: the March 2013 chain fork, where a Berkeley DB lock-limit discrepancy between client versions split the network temporarily. Bitcoin Core migrated blockchain index storage to LevelDB in version 0.8.0 (2013), gaining both performance and a more predictable, self-contained engine. Wallets kept using Berkeley DB longer; modern Bitcoin Core wallets use SQLite. Three different storage engines, each chosen for a different access pattern — the whole system is a lesson in fitting the tool to the job.

The UTXO set: why this design matters

The genius of separating UTXO state from block archive is validation efficiency. To check a new transaction, a node doesn't scan the entire multi-hundred-gigabyte chain — it queries the comparatively small UTXO set in LevelDB: do these inputs exist, are they unspent, do the amounts and scripts satisfy the rules? Spend an output and it's deleted from the set; create outputs and they're added. The UTXO set is the current state, kept small and fast, while the flat files remain the immutable historical record you only replay when verifying from scratch or reorganizing.

LevelDB's reach beyond Bitcoin

The same engine (and its descendants) shows up widely: RocksDB (Meta's server-optimized fork) powers countless databases; Ethereum's Geth client and Chrome's IndexedDB have used LevelDB-family stores. It's a quiet workhorse of modern systems — worth knowing not because you'll write one, but because recognizing "this is an LSM-tree key-value store" tells you instantly how a system will behave under write-heavy load.

Bitcoin Core doesn't use one database — it uses the right storage for each access pattern: flat files for the append-only archive, LevelDB's LSM-tree for the hot UTXO set, SQLite for wallets. That separation is why a full node validates the whole chain on a laptop.

← All articles

Research and direction by Ioannis (John) Konstas; compiled and finalized with AI assistance.

👁· views