SD System Design In Depth
0%
lesson system-designstorage-engines

Bitcask storage engine

Module 2.3: Storage Engine Internals & Blob Systems Updated Sep 17, 2026
📄 Cheat Sheet
Bitcask Explained - A Log-Structured fast KV Store Used By Uber
Arpit Bhayani Bitcask Explained - A Log-Structured fast KV Store Used By Uber Watch on YouTube ↗

Arpit Bhayani walks through the Bitcask paper end to end: keydir, append-only data files, merge and hint files, exactly this unit's scope.

0:00 / --:--

Under the Hood: The Bitcask Architecture

Originated as the default storage engine for Basho's Riak distributed database, Bitcask is an ultra-fast key-value storage engine designed for workloads where the entire keyspace fits in RAM, but values exceed available memory. It provides predictable O(1) read and write latencies with no seeks on write (appends land in the page cache; durability depends on the configured sync strategy) and at most one disk seek on read.

Bitcask Internal Components

flowchart TD subgraph RAM ["In-Memory Hash Table: 'Keydir'"] KD1["'user:101' -> {file_id: 2, offset: 512, size: 128, ts: 16900010}"] KD2["'user:102' -> {file_id: 2, offset: 640, size: 96, ts: 16900015}"] end subgraph DiskFiles ["Disk Storage: Segment Files"] Active["Active File (Append-Only: Write Allowed)"] Older1["Immutable File 001.data (Read-Only)"] Older2["Immutable File 002.data (Read-Only)"] end WriteOp["Write: Set(K, V)"] -->|"1. Append Record"| Active Active -->|"2. Return Offset"| KD1 ReadOp["Read: Get(K)"] -->|"1. Lookup Offset"| KD1 KD1 -->|"2. pread(offset, size)"| Older2

Compaction & The Hint File Optimization

When log segments accumulate stale records, a background merge process reads immutable data files and writes only the latest valid keys to new files. To prevent having to read multi-gigabyte data files on restart to rebuild the in-memory Keydir, Bitcask writes a companion Hint File alongside each merged data file.

Each hint file entry holds the timestamp, key size, value size, value position and key: the value bytes are replaced by the position of the value in the data file. On startup, Bitcask scans the tiny hint files linearly into RAM, rebuilding the million-key Keydir in seconds.

Worked example: capacity planning

Riak's Bitcask guidance budgets a fixed overhead of roughly 40-50 bytes per key in the keydir, plus the key itself. For 200 million keys averaging 36 bytes:

  • RAM per replica: 200 million x (36 + about 45) bytes is roughly 16 GB.
  • With 3 replicas across a cluster, about 48 GB of keydir RAM in total, spread over nodes.
  • If values average 2 KB, disk per replica is about 400 GB for one live version, plus dead versions awaiting merge.

The design wins when values are large relative to keys; with 30-byte keys and 50-byte values the keydir costs as much as the data.

What is actually stored

StructureFieldsPurpose
Data file entrycrc, timestamp, key size, value size, key, valueThe durable record
Keydir entry (RAM)file id, value size, value position, timestampFind the latest value in one read
Hint file entrytimestamp, key size, value size, value position, keyRebuild the keydir without reading values

Merge, step by step

  1. Select immutable (non-active) data files whose fragmentation or dead bytes exceed a threshold.
  2. For each record, keep it only if the keydir still points at that exact file and offset.
  3. Write survivors to new merged data files and emit matching hint files.
  4. Atomically update keydir entries to the new locations, then delete the old files.

Bitcask versus an LSM-tree

PropertyBitcaskLSM-tree
Keys in RAMAllOnly indexes and filters
Point readOne read, predictableMemtable, filters, one or more blocks
Range scanNoYes
Write amplificationLow (merge only)Higher (multi-level compaction)
Check yourself Question 1 of 3
Hint file contents recall
From: Compaction & The Hint File Optimization

What does a Bitcask hint file entry contain?

Key Takeaways

Bitcask stores all keys in an in-memory hash table (Keydir) and all values in append-only disk segments.
Reads require exactly 1 disk seek; writes are sequential appends requiring 0 seeks.
Hint files store keys and byte offsets without values, enabling instant startup and crash recovery.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue