Rust edition: this page follows the live DeepWiki structure but treats the current Rust crates as implementation authority. Non-Rust surfaces are identified at their boundary and are not presented as Rust APIs.
State Persistence and Recovery
Relevant Rust source files
crates/infrastructure/src/redis/cache.rscrates/common/src/cache/mod.rscrates/common/src/cache/database.rscrates/infrastructure/src/redis/msgbus.rscrates/infrastructure/src/sql/queries.rs
State persistence and recovery enables a live trading system to survive crashes, restarts, and upgrades by saving critical trading state to durable storage and restoring it on startup. This page documents the mechanisms for persisting orders, positions, accounts, instruments, and other stateful entities, as well as the infrastructure layer for Redis and PostgreSQL.
Overview
The NautilusTrader system maintains critical state in memory within the Cache component during operation. In live trading environments, this state must be persisted to survive process restarts. The system provides two primary persistence mechanisms:
- Cache State Persistence: Long-lived entities like orders, positions, accounts, and instruments stored via the
CacheDatabaseAdapterinterface - Event Store (Authoritative Log): An append-only event store capturing commands, events, and venue reports flowing across the message bus (documented in section 2.11).
The infrastructure layer is implemented primarily in Rust for performance, providing adapters for Redis and PostgreSQL
Cache Database Architecture
Infrastructure Layer (Rust)
The core persistence logic resides in the nautilus-infrastructure crate. It utilizes a multi-connection architecture to prevent I/O blocking of the main trading loop.
Redis Cache Implementation
The RedisCacheDatabase uses two distinct Redis connections with specific roles to ensure high performance and thread safety:
- READ (
self.con): Handles synchronous queries such askeys,read, andload_all - WRITE: Managed by a background task (
CACHE_WRITE) on the Nautilus runtime. It receivesDatabaseCommandobjects (Insert, Update, Delete, Flush, Close) via an unboundedtokio::sync::mpscchannel
The infrastructure implementation may use background tasks and separate read/write connections, but the semantic boundary remains CacheDatabaseAdapter. Redis transport behind the message bus is a different lane and must not be treated as the cache or event-store durability authority.
PostgreSQL Cache Implementation
The PostgresCacheDatabase utilizes sqlx and a PgPool to persist state to a relational schema Similar to the Redis implementation, it offloads I/O to a CACHE_PROCESS task using an unbounded MPSC channel for DatabaseQuery variants
Supported Entities and Indexing
The system persists specific collections and maintains secondary indexes to allow fast recovery of specific subsets.
| Collection Key | Entities Stored | Code Reference |
|---|---|---|
instruments |
InstrumentAny |
|
accounts |
AccountAny |
|
orders |
OrderAny |
|
positions |
Position |
|
snapshots |
OrderSnapshot, PositionSnapshot |
|
custom |
CustomData |
The DatabaseQueries class in the Redis module provides utility functions for scanning keys and bulk reading data using MGET or batched MGET to avoid exceeding request size limits
MessageBus External Streaming
The infrastructure layer allows the internal MessageBus to bridge to external Redis Streams. This enables external monitoring tools or other trading nodes to subscribe to the event flow.
Background Tasks
The RedisMessageBusDatabase (documented in crates/infrastructure/src/redis/msgbus.rs) spawns specialized tasks on the Rust runtime to manage high-throughput streaming without impacting the latency of the core trading logic. This includes handling the XADD operations for outgoing messages and XREAD for incoming external events.
PostgreSQL Schema and Models
The PostgreSQL implementation uses a structured schema to represent trading entities. Mapping between Rust types and SQL rows is handled via sqlx in crates/infrastructure/src/sql/queries.rs.
- General Storage: The
generaltable stores raw key-value pairs for miscellaneous data - Currencies: Persisted in the
currencytable with fields for precision and ISO codes - Instruments: The
instrumenttable uses anON CONFLICT (id) DO UPDATEpattern to handle updates to existing instrument definitions - Orders and Events: Order state and events are stored in dedicated tables, including indexes for fast lookups by
client_order_idorvenue_order_id.
The DatabaseQueries::truncate function provides a way to reset the database by calling the truncate_all_tables() SQL function