Architecture
Welcome to the architectural overview of NautilusTrader.
This guide dives deep into the foundational principles, structures, and designs that underpin the platform. Whether you're a developer, system architect, or just curious about the inner workings of NautilusTrader, this section covers:
- The design philosophy that drives decisions and shapes the system's evolution.
- The overarching system architecture providing a bird's-eye view of the entire system framework.
- How the framework is organized to facilitate modularity and maintainability.
- The code structure that ensures readability and scalability.
- A breakdown of component organization and interaction to understand how different parts communicate and collaborate.
- And finally, the implementation techniques that are crucial for performance, reliability, and robustness.
Throughout the documentation, the term "Nautilus system boundary" refers to operations within the runtime of a single Nautilus node (also known as a "trader instance").
Design philosophy
The major architectural techniques and design patterns employed by NautilusTrader are:
- Domain driven design (DDD)
- Event-driven architecture
- Messaging patterns (Pub/Sub, Req/Rep, point-to-point)
- Ports and adapters
- Crash-only design
These techniques have been utilized to assist in achieving certain architectural quality attributes.
Quality attributes
Architectural decisions are often a trade-off between competing priorities. The below is a list of some of the most important quality attributes which are considered when making design and architectural decisions, roughly in order of 'weighting'.
- Reliability
- Performance
- Modularity
- Testability
- Maintainability
- Deployability
Assurance-driven engineering
NautilusTrader is incrementally adopting a high-assurance mindset: critical code paths should carry executable invariants that verify behaviour matches the business requirements. Practically this means we:
- Identify the components whose failure has the highest blast radius (core domain types, risk and execution flows) and write down their invariants in plain language.
- Codify those invariants as executable checks (unit tests, property tests, fuzzers, static assertions) that run in CI, keeping the feedback loop light.
- Prefer zero-cost safety techniques built into Rust (ownership,
Result
surfaces,panic = abort
) and add targeted formal tools only where they pay for themselves. - Track “assurance debt” alongside feature work so new integrations extend the safety net rather than bypass it.
This approach preserves the platform’s delivery cadence while giving mission critical flows the additional scrutiny they need.
Further reading: High Assurance Rust.