Skip to content
fdb-simulation-workloads logo

FDB Simulation Workloads

fdb-simulation-workloads

Guide for writing FoundationDB simulation workloads in Rust. Use when

SKILL.md

Full skill instructions

FDB Simulation Workloads

Patterns for designing Rust workloads that find bugs through autonomous chaos testing.

Determinism Rules (Critical)

Breaking any rule destroys reproducibility. The simulator requires identical seeds to produce identical execution paths.

Instead ofUseWhy
HashMap / HashSetBTreeMap / BTreeSetIteration order must be deterministic
rand::random()context.rnd()Seeded randomness for reproducibility
SystemTime::now()context.now()Simulation controls time
Manual retry loopsdb.run()Proper retry handling with maybe_committed
tokio::spawn()NeverSimulation uses custom executor

Operation Alphabet

Design operations across three categories:

CategoryPurposeExamples
NormalMirror production traffic distribution80% reads, 15% writes, 5% complex updates
AdversarialEdge cases customers will sendEmpty strings, max-length values, null bytes, boundary integers
NemesisDeliberately break thingsDelete random data, crash mid-batch, conflict storms, approach 10MB limit

Invariant Patterns

Verify correctness continuously during execution, not just at the end.

PatternDescriptionExample
Reference ModelIn-memory copy of expected state; compare in check phaseBTreeMap tracking all expected key-values
Conservation LawsQuantities that must remain constantTotal money across accounts unchanged
Structural IntegrityData structure validity checksIndex entries point to existing records
Operation LoggingLog intent in same transactionEliminates maybe_committed uncertainty

Three-Crate Architecture

Separate production frameworks from simulation-testable code:

my-project/
├── my-fdb-service/      # Core FDB operations - NO tokio
├── my-grpc-server/      # Production layer (tokio + tonic)
└── my-fdb-workloads/    # Simulation tests

The service crate contains pure db.run() transaction logic. The server crate wraps it for production. The workloads crate tests actual service code under chaos.

Common Pitfalls

  1. Initialization on all clients - Use if self.client_id == 0 to run setup once
  2. Ignoring maybe_committed - Check the flag in db.run() closure for idempotency
  3. Storing database references - Each phase receives fresh references; don't cache them
  4. Wrapping FdbError - Keep errors unwrapped so retry mechanism detects retryable errors
  5. Assuming setup is failure-free - FDB knobs randomize; always use db.run() with retry logic

Full Reference

For detailed examples, patterns, and rationale: https://pierrezemb.fr/posts/writing-rust-fdb-workloads-that-find-bugs/