Why my business simulator replays every run bit for bit
Description and use
Ventute achieves bit‑for‑bit deterministic replay of business simulations by storing actions as events, controlling nondeterminism, and moving the core loop to Rust via PyO3.
Problem
Ensuring deterministic replay of a business simulation so that each run can be debugged and trusted.
Outcome
Ventute now achieves deterministic, bit‑for‑bit replay of simulations, enabling reliable debugging and trust, while leveraging Rust for performance and Python for ease of use.
Workflow
- Store every action as an event rather than saving state directly.
- Rebuild state by folding the event log from the beginning.
- Control sources of nondeterminism: wall clock time, randomness, iteration order, floating point.
- Move the hot simulation loop into Rust and expose it via PyO3.
- Run simulations on real threads in parallel while keeping the API async in Python with FastAPI.
- Use PostgreSQL (Neon) for storage and Redis for caching.
- Ensure every run produces the same answer regardless of thread completion order.
Evidence
Every action in Ventute is stored as an event. The state of a company is never saved directly. It is rebuilt by folding the event log from the beginning.
The hard part is making that true every single time. Wall clock time, randomness, iteration order and floating point all love to break replay quietly.
I moved the hot loop into Rust and call it through PyO3, so the simulations run on real threads in parallel while the API stays in async Python with FastAPI.
Three patterns from Ventute turned out to be useful on their own, so I published them on GitHub under m4xkushnir.
- Record date: 2026-10-17T15:41:20.860Z