# Amadeus Protocol Node Storage Mechanisms: Mnesia KV, ETS, and RocksDB Architecture Explained

> Explore Amadeus Protocol node storage mechanisms: Mnesia KV for distributed state, ETS for caching, and optional RocksDB for large data. Understand the unified DB API.

- Repository: [Amadeus Protocol/node](https://github.com/amadeusprotocol/node)
- Tags: architecture
- Published: 2026-08-20

---

**The Amadeus Protocol node uses a layered storage stack combining Mnesia KV for durable distributed state, ETS for in-memory caching, and optional RocksDB for large binary data, all abstracted behind a unified DB API.**

The Amadeus Protocol node is an Elixir-based blockchain implementation that must balance **durability**, **performance**, and **distributed consistency** across its network participants. Its storage architecture reflects these trade-offs through a careful separation of concerns: persistent state survives restarts and propagates across nodes, ephemeral caches optimize hot-path reads, and pluggable backends accommodate different deployment scenarios. This article examines the storage mechanisms as implemented in the [amadeusprotocol/node](https://github.com/amadeusprotocol/node) repository, with direct references to source file paths and function signatures.

## Core Storage Mechanisms

The node organizes storage into three primary tiers, each serving distinct operational requirements.

### Mnesia KV: Distributed Persistent Store

**Mnesia KV** is the foundational storage mechanism for data that must survive node restarts and maintain consistency across the distributed system. Built on Erlang's Mnesia database, it provides **atomic transactions**, **table replication**, and **disc-based persistence** with minimal operational overhead.

Mnesia KV tables are defined and accessed through dedicated modules that encapsulate schema details:

| Table | Module | Purpose |
|-------|--------|---------|
| `ReplicaKV` | [`ex/lib/node/replica_gen.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/node/replica_gen.ex) | Tracks replica high-water marks for slashing prevention |
| `NODEANR` | [`ex/lib/node/node_anr.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/node/node_anr.ex) | Stores anti-replay nonces to prevent transaction replay attacks |

The `MnesiaKV` module exposes a functional API for CRUD operations. Writes are synchronous and transactional, ensuring that critical state mutations—such as updating the last signed block height—are durably recorded before the operation returns.

```elixir

# Update replica high-water mark in Mnesia KV

{:ok, _} =
  MnesiaKV.merge(
    ReplicaKV,
    "last_signed_height",
    %{height: new_height}
  )

```

On node startup, these tables are reloaded from disk, allowing the replica generator to resume from its last known position without external coordination. The [`node_anr.ex`](https://github.com/amadeusprotocol/node/blob/main/node_anr.ex) module similarly retrieves persisted anti-replay entries to validate incoming transactions:

```elixir

# Retrieve anti-replay entry from Mnesia KV

case MnesiaKV.get(NODEANR, pk) do
  nil -> :not_found
  anr -> {:ok, anr}
end

```

### ETS: In-Memory Runtime Caching

**ETS (Erlang Term Storage)** provides **fast, read-optimized access** to data that can be reconstructed from persistent storage or is transient by nature. Unlike Mnesia, ETS tables reside entirely in memory and are **cleared on node restart**, trading durability for speed and simplicity.

The [`ex/lib/node/node_state.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/node/node_state.ex) module initializes ETS tables during the node supervision tree startup, populating them from Mnesia or computing values on demand. Typical ETS use cases include:

- Cached peer connection lists
- Recently processed block headers
- Runtime configuration snapshots

ETS operations bypass Mnesia's transaction overhead, yielding **microsecond-level read latencies** for hot data paths.

### RocksDB/LevelDB: Embedded Backend for Large Values

For deployments handling substantial binary payloads—such as contract state merkle trees or historical attestation proofs—the node supports an **optional RocksDB or LevelDB backend**. This embedded key-value store complements Mnesia by offloading large values that would degrade Mnesia's performance characteristics.

The backend selection is **configuration-driven** and transparent to calling code through the abstraction layer. When enabled, the following modules delegate to the embedded database:

| Module | Responsibility |
|--------|--------------|
| [`ex/lib/api/db_chain.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/db_chain.ex) | Block and header persistence |
| [`ex/lib/api/db_entry.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/db_entry.ex) | General entry storage |
| [`ex/lib/api/db_attestation.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/db_attestation.ex) | Attestation record keeping |

```elixir

# Read through the generic DB API—backend selection is transparent

{:ok, entry} = DBAPI.get(:chain, key)

# Resolves to Mnesia or RocksDB based on :node configuration

```

## Specialized Storage: Merkle Mountain Ranges

The **Merkle Mountain Range (MMR)** is a cryptographic accumulator structure used for compact proofs of chain history. Implemented in [`ex/lib/api/db_mmr.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/db_mmr.ex), it persists its internal nodes through the generic DB layer—meaning MMR data resides in whichever backend (Mnesia or RocksDB) is active.

This design allows the node to:

- Generate inclusion proofs for any historical block without full chain traversal
- Prune obsolete MMR peaks while retaining verification capability
- Switch storage backends without invalidating accumulated proof data

## Storage Abstraction and Pruning

All storage mechanisms converge through **[`ex/lib/api/db_api.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/db_api.ex)**, which exposes a **uniform CRUD interface** regardless of the underlying implementation. This abstraction enables:

- **Development defaults**: Pure Mnesia mode for local testing
- **Production scaling**: Mixed mode with RocksDB for I/O-heavy workloads
- **Seamless migration**: Backend swaps without application code changes

To prevent unbounded growth, the **[`ex/lib/api/db_pruner.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/db_pruner.ex)** module implements **time-based and height-based retention policies**. The pruner operates against the generic DB API, ensuring consistent cleanup across Mnesia and RocksDB deployments:

```elixir

# Execute pruning job—works with any configured backend

:ok = DBPruner.prune(:chain, older_than: :days_30)

```

Pruning is **asynchronous and incremental**, scanning and deleting entries in batches to minimize impact on consensus-critical operations.

## Configuration and Operational Flexibility

The node's storage stack is **not monolithic**—operators can tune the trade-off between consistency, performance, and resource utilization through application configuration. The default development profile uses Mnesia exclusively, while production deployments may enable RocksDB for the chain and entry tables while retaining Mnesia for replica state and anti-replay data.

This flexibility is achieved without code duplication because all storage consumers interact through the `DBAPI` contract, with backend routing resolved at runtime based on table-specific configuration.

## Summary

- **Mnesia KV** provides durable, distributed, transactional storage for critical consensus state including replica high-water marks and anti-replay nonces
- **ETS** delivers microsecond-latency in-memory caching for reconstructible or transient runtime data
- **RocksDB/LevelDB** (optional) handles large binary payloads that would degrade Mnesia performance
- **Merkle Mountain Ranges** implement cryptographic history proofs atop the generic DB layer
- **DB API abstraction** unifies access patterns and enables backend portability
- **Pruning subsystem** enforces retention policies across all storage backends

## Frequently Asked Questions

### What is Mnesia KV in the Amadeus Protocol node?

Mnesia KV is the node's primary persistent storage mechanism, built on Erlang's Mnesia distributed database. It provides atomic transactions, disc-based durability, and table replication across cluster nodes. The implementation in [`ex/lib/node/replica_gen.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/node/replica_gen.ex) and [`ex/lib/node/node_anr.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/node/node_anr.ex) uses `MnesiaKV.merge/3` and `MnesiaKV.get/2` for synchronous, crash-safe state updates.

### When does the node use ETS instead of Mnesia?

ETS is used for **transient or reconstructible data** where durability is unnecessary and speed is paramount. The [`ex/lib/node/node_state.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/node/node_state.ex) module initializes ETS tables at startup for cached peer lists, recent headers, and runtime snapshots. Unlike Mnesia, ETS tables vanish on node restart and offer no cross-node replication.

### Can the Amadeus Protocol node run without RocksDB?

Yes. RocksDB is **strictly optional**. The default configuration uses Mnesia for all storage needs, which is suitable for development and moderate-scale deployments. RocksDB is enabled through configuration to improve performance when storing large contract state or extensive historical data, but the `DBAPI` abstraction ensures identical behavior regardless of backend selection.

### How does the node prevent storage from growing indefinitely?

The [`ex/lib/api/db_pruner.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/db_pruner.ex) module implements **automated pruning** with configurable retention policies. It scans chain, entry, and attestation tables via the generic `DBAPI`, removing entries older than specified thresholds. Pruning runs asynchronously in batches to avoid blocking consensus operations, and works uniformly across Mnesia and RocksDB backends.