# What Raft State Does OpenRaft Storage Manage? Complete Technical Guide

> OpenRaft storage manages the complete RaftState C struct including vote history log identifiers membership configurations server role and more to ensure full consensus participation after node restarts.

- Repository: [Databend Labs/openraft](https://github.com/databendlabs/openraft)
- Tags: deep-dive
- Published: 2026-02-28

---

**OpenRaft storage persists and reconstructs the complete `RaftState<C>` struct, encompassing vote history, log identifiers, membership configurations, snapshot metadata, server role, I/O progress tracking, and compaction markers to restore full consensus participation after node restarts.**

The `databendlabs/openraft` repository implements a Raft consensus engine where the storage layer serves as the authoritative source of truth for node recovery. Understanding what Raft state OpenRaft storage manages is essential for operators implementing custom `RaftLogStorage` and `RaftStateMachine` traits. The system captures every critical piece of consensus metadata required to resume operation after crashes or planned restarts.

## Core Components of OpenRaft Storage State

The `RaftState<C>` struct defined in [`openraft/src/raft_state/mod.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/raft_state/mod.rs) aggregates all persistent and semi-volatile state needed for consensus. According to the OpenRaft source code, storage implementations must track eight distinct categories of state.

### Vote and Election State

The `vote` field stores a `Leased<VoteOf<C>, InstantOf<C>>` containing the current term, voted-for candidate, and commitment status. This field appears at lines 65-68 in [`openraft/src/raft_state/mod.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/raft_state/mod.rs) and ensures nodes respect previously granted votes across restarts, preventing split-brain scenarios during leader election.

### Log History and Metadata

Storage maintains `log_ids: LogIdList<C>` (lines 68-70), an ordered collection of all log IDs including purged ranges. This allows the node to reconstruct its log position and validate append requests from leaders without scanning the entire log store.

### Cluster Membership Configuration

The `membership_state: MembershipState<C>` field (lines 71-73) persists the latest cluster membership configuration, whether stored in the log or state machine. This enables safe configuration changes across node restarts without losing track of quorum requirements.

### Snapshot Metadata

`snapshot_meta: SnapshotMeta<C>` (lines 74-76) records the last included log ID, checksums, and other metadata for the most recent snapshot. This facilitates state machine recovery and log compaction decisions after reboots.

### Server Role and I/O Progress

While `server_state: ServerState` (lines 82-84) tracks the current role (Leader, Candidate, Follower, or Learner), the `io_state: Valid<IOState<C>>` field (lines 85-87) monitors volatile I/O progress including pending log replications and snapshot installations. The `purge_upto: Option<LogIdOf<C>>` marker (lines 91-92) indicates safe deletion boundaries for log compaction, while `progress_id_gen: SharedIdGenerator` (lines 93-94) manages unique identifiers for inflight replication tasks.

## How OpenRaft Storage Reconstructs Raft State on Startup

When initializing a `Raft` node, the system relies on `StorageHelper::get_initial_state()` in [`openraft/src/storage/helper.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/storage/helper.rs) (lines 81-152) to assemble the complete state from persistent storage.

The method performs six critical restoration steps:

1. **Reading the last vote** via `log_reader.read_vote()` with fallback defaults for new nodes
2. **Fetching log bounds** through `log_store.get_log_state()` to obtain `last_purged_log_id` and `last_log_id`
3. **Retrieving applied index** from `state_machine.applied_state()` to determine committed state
4. **Synchronizing committed index** to ensure `committed ≥ last_applied`
5. **Restoring snapshots** and re-applying persisted logs after snapshot points
6. **Loading membership** via `self.get_membership().await`

```rust
use openraft::Raft;
use openraft::storage::StorageHelper;

// Assume `store` implements `RaftLogStorage` and `sm` implements `RaftStateMachine`
let mut helper = StorageHelper::new(&mut store, &mut sm)
    .with_id(node_id);

let raft_state = helper.get_initial_state().await?;
// raft_state now contains vote, log_ids, membership_state, snapshot_meta, etc.

```

The `Raft::new()` constructor (approximately line 471 in [`openraft/src/raft/mod.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/raft/mod.rs)) consumes this state to initialize the consensus engine.

## Key Source Files for OpenRaft Storage State

Understanding the storage architecture requires familiarity with these specific files:

- [`openraft/src/raft_state/mod.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/raft_state/mod.rs) – Definition of `RaftState<C>` and its constituent fields
- [`openraft/src/storage/helper.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/storage/helper.rs) – High-level state reconstruction via `StorageHelper::get_initial_state()`
- [`openraft/src/storage/v2/raft_log_storage.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/storage/v2/raft_log_storage.rs) – `RaftLogStorage<C>` trait providing `read_vote()` and `get_log_state()` APIs
- [`openraft/src/storage/v2/raft_state_machine.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/storage/v2/raft_state_machine.rs) – `RaftStateMachine<C>` trait for applied state and snapshots
- [`openraft/src/raft/mod.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/raft/mod.rs) – Integration point where storage state initializes the Raft engine

## Summary

- OpenRaft storage manages eight categories of state within `RaftState<C>`: votes, log IDs, membership, snapshots, server role, I/O progress, purge markers, and ID generation
- The `StorageHelper::get_initial_state()` method orchestrates reconstruction from `RaftLogStorage` and `RaftStateMachine` implementations during node startup
- State restoration involves reading votes, log bounds, applied indices, and membership configurations to establish a consistent starting point for consensus participation
- All state definitions reside in [`openraft/src/raft_state/mod.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/raft_state/mod.rs) while reconstruction logic lives in [`openraft/src/storage/helper.rs`](https://github.com/databendlabs/openraft/blob/main/openraft/src/storage/helper.rs)

## Frequently Asked Questions

### What is the difference between RaftLogStorage and RaftStateMachine in OpenRaft?

`RaftLogStorage` persists log entries, votes, and log metadata via methods like `read_vote()` and `get_log_state()`, while `RaftStateMachine` maintains the actual application state and applied indices through `applied_state()`. `StorageHelper::get_initial_state()` coordinates between both traits to build the complete `RaftState<C>` during node initialization.

### Does OpenRaft storage maintain volatile state across restarts?

Most fields in `RaftState<C>` are persistent, but `io_state` and `server_state` are reconstructed or reset during initialization. Only the vote, log IDs, membership configuration, and snapshot metadata survive crashes and must be durably stored by implementations of `RaftLogStorage` and `RaftStateMachine`.

### How does OpenRaft prevent split-brain scenarios after node restarts?

The storage layer persists the `vote` field as a `Leased<VoteOf<C>, InstantOf<C>>`, recording previously granted votes with timestamps. Upon restart, `StorageHelper::get_initial_state()` reads this via `log_reader.read_vote()`, ensuring nodes honor existing votes in the current term and preventing multiple leaders from being elected in the same term.

### What happens if OpenRaft storage returns inconsistent log state during initialization?

`get_initial_state()` validates consistency between `last_applied` from the state machine and `committed` indices from the log store, ensuring `committed ≥ last_applied`. Inconsistencies surface as `StorageError` exceptions that prevent node startup until administrative intervention resolves the divergence.