# IAVL v2 Design Highlights
Disk:
- Separate tree per store key
- Separate db per store key (unlocks concurrent writes)
- Separate tree/leaf per db (unlocks concurrent writes)
Key format:
- same as IAVL v1 (version, sequence)
- version is block height, sequence is insertion order in version _n_.
At every block commit:
- Hash tree, write root node with hash.
- Write leaf nodes, write leaf deletes. This forms a WAL for replay.
- Determine if tree should checkpoint, if yes write all dirty tree nodes.
- The above means that dirty tree nodes *must* remain in memory!
- When the tree is checkpointing version _n_, and the last checkpoint was version _m_, only nodes with _version > m_ are present in the version _n_ checkpoint.
Cache:
- IAVL v2 doesn't have a secondary cache; the tree stored in memory is the cache.
- Eviction policy is based on layers/height and memory estimation.
- Cache close to ceiling with dirty nodes triggers a checkpoint.
Replay:
- To load a tree at version _n_, load the most recent checkpoint m where _m < n_ then replay the leaf changes since that version.
- When not running in archive mode, historical proof support replays the tree to provide a proof.
Prune:
- Remove _orphaned_ tree nodes from old checkpoints. A node is orphaned in version _n_ when it no longer has any references in that version of the tree.
Archive mode (not yet implemented)
- Same as above but checkpoint at every version.
- Therefore no need for replays between checkpoints
### Why SQLite?
- WAL mode supports many readers with a single concurrent writer
- BTrees faster than LSM on read and IAVL workloads are read heavy
- Bulk writes are very fast (profiled faster than leveldb)