Firewood Database
Learn about Firewood, the compaction-less database optimized for efficiently storing Merkleized blockchain state.
Firewood is a purpose-built embedded key-value store optimized for storing recent Merkleized blockchain state. Unlike traditional blockchain storage approaches that layer Merkle tries on top of generic databases, Firewood stores trie nodes directly on disk, eliminating compaction overhead and enabling superior performance.
Note
Source Code: github.com/ava-labs/firewood
Summary
Firewood reimagines blockchain state storage with several key innovations:
- Native trie storage: Stores Merkle trie nodes directly on disk
- No compaction: Eliminates expensive compaction cycles
- Recent state focus: Optimized for storing recent revisions
- Disk-offset addressing: Root addresses are disk offsets, not hashes
Warning
Firewood is beta-level software. The Firewood API may change with little to no warning.
The Problem with Traditional Approaches
Most blockchain clients (including Ethereum's Geth and traditional AvalancheGo) store state using generic key-value databases like LevelDB or RocksDB. This creates a fundamental mismatch:
Problems with Generic KV Stores
| Issue | Description |
|---|---|
| Double indexing | Trie structure is flattened into KV pairs, then re-indexed by the database |
| Compaction overhead | LSM-trees require periodic compaction that causes latency spikes |
| Write amplification | Data is rewritten multiple times during compaction |
| Hash-based lookup | Finding a node requires hashing, then database lookup |
How Firewood Works
Firewood implements a Patricia trie (a specific variant of radix tree) natively on disk, using the trie structure itself as the index.
Native Trie Storage
Key design decisions:
- Disk offset = address: A node's address is simply its offset in the database file
- Direct pointers: Branch nodes point to disk offsets of child nodes
- No hash lookup: Finding a node doesn't require computing or looking up hashes
Revision Management
Firewood implements a persistent (immutable) trie structure that supports multiple concurrent versions:
When state is updated:
- New versions of modified nodes are created
- Unchanged subtrees are shared between revisions
- Old revisions remain accessible for reads
Future-Delete Log (FDL)
Firewood tracks which nodes become obsolete:
This enables:
- Predictable cleanup: No sudden compaction pauses
- Inline compaction: Space is reclaimed as part of normal operation
- Configurable history: Retain as many revisions as needed
Technical Architecture
Core Components
firewood/
├── firewood/ # Database core: revisions, proposals, proofs
├── storage/ # Node store, free lists, hashing
├── ffi/ # Go bindings (CGo)
├── fwdctl/ # Command-line tool
├── triehash/ # Ethereum trie hash helpers
└── benchmark/ # BenchmarksFree Space Management
Firewood manages free space similarly to heap memory allocation:
When allocating space for new nodes:
- Check free lists for appropriate size
- If no suitable free space, allocate from end of file
- When revisions expire, return space to free lists
Key Features
Concurrent Access
Firewood efficiently synchronizes between:
| Actor | Role |
|---|---|
| Writer (Execution) | Single writer commits new state |
| Readers (Consensus, RPC) | Multiple readers access historical state |
The persistent trie structure ensures:
- Readers always see consistent state
- Writes are atomic from readers' perspective
- No locks required for read operations
Sequential Writes
Firewood allocates space for a new node from the free list of the matching size. If no free slot fits, it appends the node at the end of the file:
| State | Slot 1 | Slot 2 | Slot 3 | Slot 4 | Slot 5 |
|---|---|---|---|---|---|
| Before | Node A | Node B | Node C | Free | Free |
| After | Node A | Node B | Node C | Node D | Node E |
Benefits for SSDs:
- Entire blocks are filled before moving to the next
- Simplified garbage collection
- Reduced write amplification
- Increased SSD longevity
Proofs and State Sync
Firewood natively supports proof generation:
| Proof Type | Description |
|---|---|
| Key Proof | Proves a key exists in a specific revision |
| Range Proof | Proves a range of keys with all values |
| Change Proof | Proves differences between two revisions |
These proofs enable efficient state sync without trusting the source.
Ethereum Compatibility
By default, Firewood uses SHA256 hashing (compatible with MerkleDB). For Ethereum compatibility, enable the ethhash feature:
# Build with Ethereum-compatible hashing
cargo build --features ethhashThis changes:
- Hashing algorithm: SHA256 → Keccak256
- Account handling: Understands RLP-encoded accounts
- Storage trie: Computes account storage roots correctly
Note
The ethhash feature has some performance overhead compared to the default configuration.
Performance Characteristics
Compared to LevelDB/RocksDB
| Metric | Traditional | Firewood |
|---|---|---|
| Write amplification | High (compaction) | Low (no compaction) |
| Latency spikes | Periodic (compaction) | Minimal |
| Iteration speed | Fast | Fast (native trie) |
| Proof generation | Requires reconstruction | Native support |
| Space efficiency | Good after compaction | Configurable |
Location in AvalancheGo
Firewood stores its data in regular files. On the C-Chain, AvalancheGo puts the Firewood files in {chain-data-dir}/{blockchainID}/firewood. The default chain-data-dir is $HOME/.avalanchego/chainData.
Metrics
Firewood provides comprehensive Prometheus metrics:
# Revisions held in memory, and the configured limit
firewood_revisions_active
firewood_revisions_limit
# Revisions written to disk
firewood_commits_total
# Commit latency
firewood_proposal_commit_duration_seconds
# Space reused from free lists, appended at the end of the file, and freed
firewood_storage_bytes_reused_total
firewood_storage_bytes_appended_total
firewood_storage_bytes_freed_totalSee METRICS.md for the complete metrics reference.
Command Line Interface
Firewood includes fwdctl for database operations:
# Create a new database
fwdctl create --db /data/firewood --node-hash-algorithm merkle-db
# Insert a key-value pair
fwdctl insert --db /data/firewood key1 value1
# Query data
fwdctl get --db /data/firewood key1
# Show the root hash
fwdctl root --db /data/firewoodIntegration with AvalancheGo
Firewood stores the state trie of an EVM chain. It does not replace the node database. The node database (LevelDB or PebbleDB, set with --db-type) still stores blocks and other chain data. Select Firewood for each chain with the state-scheme option in the chain config.
Warning
Firewood is an EXPERIMENTAL state scheme. To use it on the C-Chain, set "state-scheme": "firewood" in {chain-config-dir}/C/config.json. A Firewood C-Chain node cannot state sync. On Mainnet and Fuji, also set "state-sync-enabled": false, or the node shuts down with a FATAL error. The node then bootstraps by executing every block from genesis. AvalancheGo uses the Go bindings from firewood-go-ethhash.
Related Resources
Continuous Execution
How Continuous Execution leverages Firewood for efficient execution
Core Components
AvalancheGo's overall architecture
External Links
Is this guide helpful?