Storage (StableDB)
Stable v1.4.0 replaces the LevelDB-backed state store with MemIAVL. MemIAVL keeps one state snapshot in a memory-mapped file and records each new block's changes in a sequential write-ahead log.
Why disk I/O is a bottleneck
Every block changes the application state. A node must complete two related tasks:
- State commitment: calculate and commit the root hash for the new state.
- State persistence: write the changed data to storage so the node can recover it later.
The previous LevelDB-backed store coupled these tasks. It also rewrote data during background compaction, which reorganizes stored records to make later reads efficient.
One logical state update could cause 10–50 times as much physical disk writing. This is called write amplification. Execution then had to wait for a storage path dominated by random writes and compaction.
How MemIAVL changes the store
A memory-mapped file, or mmap, lets the operating system expose file contents through memory addresses. The node can read state by following pointers, while the operating system loads the required pages into its page cache.
MemIAVL combines two structures:
- Snapshot: one memory-mapped representation of the persisted state tree.
- Write-ahead log (WAL): an append-only record of raw changes made after that snapshot.
Write path
Each block appends its change set to the WAL in sequence. MemIAVL does not route the update through LevelDB or trigger compaction. Write amplification therefore falls from 10–50 times to approximately one write.
MemIAVL also separates tree nodes into two categories:
PersistedNoderepresents an unchanged subtree already stored in the snapshot.MemNoderepresents a subtree changed in memory by the current updates.
When MemIAVL calculates the next root hash, it stops at unchanged PersistedNode subtrees. It hashes only the paths containing new MemNode data.
Read path
Current-state reads follow pointers into the memory-mapped snapshot. Frequently accessed pages remain in the operating system's page cache, so the node avoids a separate database lookup for each tree node.
Historical state and VersionDB
MemIAVL serves the current state and the snapshots a node retains. A companion VersionDB stores historical versions in a RocksDB sidecar.
You need VersionDB when the node must answer historical state queries older than its earliest retained MemIAVL snapshot. This is especially important for archive nodes and RPC services that expose long-range queries.
Migration considerations
Existing nodes must migrate their LevelDB state when they adopt v1.4.0. The recommended path is a local snapshot export and restore.
Benchmarks measured an average of 19.4 seconds of downtime per validator for the standard restore. A parallel restore variant reduced the average to approximately 2.6 seconds.
Validators can migrate one at a time in round-robin order. Keeping at least two-thirds of voting power online lets the network continue producing blocks during the migration.
Further reading
For more technical deep-dives and implementation details, refer to:
- ADR-065: Cosmos Store V2 Architecture
- MemIAVL: A Practical Guide
- Cronos MemIAVL Node Configuration
- Sei’s DB Design Approach
Where to go next
- High performance RPC: See how the RPC layer exposes state reads without contending with writes.
- Execution: Understand how execution writes into the storage layer covered here.
- Upgrade a node: Prepare backups and verify a node after a coordinated upgrade.
- Network upgrades: Review the complete v1.4.0 scope and rollout status.

