# Fuel Core Database Schema: A Comprehensive Guide to the Storage Layer

> Explore the Fuel Core database schema, a type-safe key-value storage layer defined in fuel-core-storage. Understand how logical entities map to tables with specific Key and Value types for efficient data management.

- Repository: [Fuel Labs/fuel-core](https://github.com/FuelLabs/fuel-core)
- Tags: architecture
- Published: 2026-03-06

---

**The Fuel Core database schema is a key-value storage layer built on the `fuel-core-storage` crate, where each logical entity (blocks, contracts, coins) is defined as a type-safe table implementing the `Mappable` trait with specific Key and Value types defined in [`crates/storage/src/tables.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/storage/src/tables.rs).**

The Fuel Core storage layer, maintained in the `FuelLabs/fuel-core` repository, persists all on-chain state using a structured key-value approach rather than a relational model. Understanding the **Fuel Core database schema** is essential for developers building indexers, block explorers, or custom tooling that needs direct access to the chain's historical and current state.

## Core Architecture of the Fuel Core Storage Layer

Fuel Core organizes its persistent storage into discrete tables that map directly to blockchain primitives. Unlike traditional SQL databases, this schema uses a strongly-typed key-value design where each table is a Rust struct implementing the `Mappable` trait.

### The Mappable Trait Pattern

Every storage table in [`crates/storage/src/tables.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/storage/src/tables.rs) defines four associated types that enforce type safety at the database boundary:

- **Key**: The primary identifier type used for lookups
- **OwnedKey**: The concrete Rust type serialized as the database key (e.g., `BlockHeight`, `ContractId`)
- **Value**: The type returned by read operations, usually a reference
- **OwnedValue**: The concrete Rust type persisted as the serialized value (e.g., `CompressedBlock`, `ContractUtxoInfo`)

This pattern ensures that operations like `db.get::<FuelBlocks>(height)` are compile-time checked against the actual schema definitions.

## Complete Database Schema Reference

The canonical table definitions reside in [`crates/storage/src/tables.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/storage/src/tables.rs). The following tables comprise the core **Fuel Core database schema**:

| Table | OwnedKey | OwnedValue | Description |
|-------|----------|------------|-------------|
| **FuelBlocks** | `BlockHeight` | `CompressedBlock` | Serialized block headers and transactions indexed by height |
| **ContractsLatestUtxo** | `ContractId` | `ContractUtxoInfo` | Current state/UTXO information for deployed contracts |
| **SealedBlockConsensus** | `BlockHeight` | `Consensus` | Finalized consensus metadata for sealed blocks |
| **Coins** | `UtxoId` | `CompressedCoin` | Individual UTXO entries representing spendable coins |
| **Messages** | `Nonce` | `Message` | Bridged messages originating from Ethereum |
| **Transactions** | `TxId` | `Transaction` | Full transaction objects indexed by transaction ID |
| **ProcessedTransactions** | `TxId` | `()` | Deduplication marker table preventing replay |
| **ConsensusParametersVersions** | `ConsensusParametersVersion` | `ConsensusParameters` | Versioned consensus configuration storage |
| **StateTransitionBytecodeVersions** | `StateTransitionBytecodeVersion` | `Bytes32` | Merkle roots of state transition bytecode uploads |

### Merkle Tree Storage Tables

The schema includes auxiliary tables under the `merkle` module for maintaining cryptographic proofs. These include `FuelBlockMerkleData` (mapping `u64` indices to binary primitives) and metadata tables like `DenseMerkleMetadata` keyed by `DenseMetadataKey<BlockHeight>`. These support sparse and dense Merkle tree operations required for state root calculations.

## Database Implementation and Wiring

The `GenericDatabase` struct in [`crates/fuel-core/src/database/storage.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/database/storage.rs) wraps the underlying key-value engine (typically RocksDB) and implements the `StorageMutate`, `StorageWrite`, and `StorageBatchMutate` traits for any type implementing `Mappable`.

This architecture enables:

- **Atomic transactions**: Batched writes through `StorageTransaction` ensure all-or-nothing commits across multiple tables
- **Read-only views**: The `ReadView` type exposes per-table iterators without blocking writers
- **Merkle proof generation**: `MerkleizedTableColumn` implementations allow cryptographic verification of any table column

The generic design means adding a new table only requires defining a new `Mappable` type in [`tables.rs`](https://github.com/FuelLabs/fuel-core/blob/main/tables.rs) and implementing the trait for the database handle.

## Practical Examples: Querying the Fuel Core Database

### Inserting a Block Atomically

```rust
use fuel_core_storage::structured_storage::StructuredStorage;
use fuel_core_storage::StorageBatchMutate;
use fuel_core_types::blockchain::block::CompressedBlock;
use fuel_core_types::fuel_types::BlockHeight;

// db is a GenericDatabase instance wrapping RocksDB
let block_height: BlockHeight = 42.into();
let block: CompressedBlock = /* block construction */;

// Atomic batch insert into FuelBlocks table
db.insert_batch::<FuelBlocks>(std::iter::once((&block_height, &block)))?;

```

### Querying Contract State

```rust
use fuel_core_storage::ReadView;
use fuel_core_types::fuel_types::ContractId;

// Obtained from ReadDatabase via GraphQL resolver or direct access
let contract_id: ContractId = /* contract identifier */;
let utxo_info = read_view
    .contract_latest_utxo(contract_id)?
    .map(|(_, info)| info); // Returns ContractUtxoInfo

```

### Streaming the UTXO Set for Snapshots

```rust
use fuel_core_storage::ReadView;
use futures::StreamExt;

// Efficient iteration over all coins without loading into memory
let mut stream = read_view.table::<Coins>()?.iter();
while let Some(Ok((utxo_id, coin))) = stream.next().await {
    // Process each CompressedCoin entry
}

```

These examples demonstrate how the `StructuredStorage` API abstracts the underlying key-value operations while maintaining the type guarantees defined in the schema.

## Summary

- The **Fuel Core database schema** is defined in [`crates/storage/src/tables.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/storage/src/tables.rs) using the `Mappable` trait pattern
- Each table specifies concrete `OwnedKey` and `OwnedValue` types for type-safe storage
- Core entities include `FuelBlocks`, `Coins`, `ContractsLatestUtxo`, and `Messages`
- The `GenericDatabase` wrapper in [`crates/fuel-core/src/database/storage.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/database/storage.rs) implements atomic batch operations and Merkle proof generation
- Read operations use `ReadView` for non-blocking access, while writes support transactional batches via `StorageBatchMutate`

## Frequently Asked Questions

### What database backend does Fuel Core use?

Fuel Core uses RocksDB as its default storage backend, wrapped by the `GenericDatabase` type. The storage layer abstracts the backend through the `Mappable` trait system, allowing the same schema definitions to work across different key-value implementations if needed.

### How does Fuel Core handle atomic transactions?

Atomicity is achieved through the `StorageBatchMutate` trait implemented by `GenericDatabase`. Operations like `insert_batch` group multiple table modifications into a single atomic unit. If any part of the batch fails, the entire transaction is rolled back, ensuring consistency across related tables like `FuelBlocks` and `Transactions`.

### What is the difference between the Transactions and ProcessedTransactions tables?

The `Transactions` table stores the full `Transaction` objects indexed by `TxId`, allowing retrieval of transaction data for blocks. The `ProcessedTransactions` table uses the same `TxId` as a key but stores only a unit type `()` as the value, serving as a lightweight deduplication marker to prevent transaction replay without storing duplicate data.

### Where are Merkle roots stored in the schema?

Merkle metadata is stored in dedicated tables within the `merkle` module, including `DenseMerkleMetadata` keyed by `DenseMetadataKey<BlockHeight>`. The actual Merkle tree data resides in `FuelBlockMerkleData` (mapping `u64` to binary values), while state transition bytecode roots are stored in `StateTransitionBytecodeVersions` as `Bytes32` values.