Skip to content
NEW BENCHMARKS

SurrealDB 3.x by the numbers

View

1/3

Deterministic simulation testing and its use at SurrealDB

Engineering

Jun 19, 20263 min read

Dave MacLeod

Dave MacLeod

Show all posts

Deterministic simulation testing and its use at SurrealDB

Our newsletter

Get tutorials, AI agent recipes, webinars, and early product updates in your inbox every two weeks

In today's engineering blog post we introduce a much longer post by Farhan Khan, a Senior Software Engineer at SurrealDB who works among other things on our distributed transactional key-value store and our own embedded key-value engine, SurrealKV.

The post is about DST (deterministic simulation testing), and can be read in full .

DST is a type of testing that aims to have the best of both worlds in both areas:

  • Coverage: writing tests that span as large an area as possible in order to find and resolve bugs before they are discovered in production.
  • Reproducibility: writing tests that reproduce the same output every time regardless of their complexity.

The blog post is quite lengthy and contains a number of runnable diagrams to demonstrate the testing behaviour it introduces. Here is a very quick tl;dr of each of its four sections to give a taste of what maks it such a fascinating read.

What deterministic simulation testing actually is

This part of the blog post goes over the difference between pure functions and impure functions...

// Same price + same qty = always the same result
fn checkout_total(price: u64, qty: u64) -> u64 {
    price * qty
}

// A function that depends on a hidden input.
// Now the output is not always guaranteed
use std::time::{SystemTime, UNIX_EPOCH};

fn checkout_total(price: u64, qty: u64) -> u64 {
    let subtotal = price * qty;
    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    if now % 20 == 0 {        // a "discount" that fires on 1 call in 20
        subtotal / 2
    } else {
        subtotal
    }
}

...and how to take seemingly random and unpredictable behaviour and make it reproducible: for example, by using the same random seed.

Building upon tokio

Rust's tokio async runtime actually comes built in with testing tools that allow you to control simulations! Here is one code example from that section.

fn build_runtime(sim_seed: u64, node_name: &str) -> Result<Runtime, Error> {
    let mut builder = tokio::runtime::Builder::new_current_thread();
    builder.enable_time().start_paused(true);

    #[cfg(all(feature = "tokio-rng-seed", tokio_unstable))]
    {
        use rand::RngCore;

        let node_seed =
            crate::prng::Prng::derive_stream(sim_seed, node_name.as_bytes()).next_u64();

        builder.rng_seed(tokio::runtime::RngSeed::from_bytes(
            &node_seed.to_le_bytes(),
        ));
    }

    let _ = (sim_seed, node_name);

    builder
        .build()
        .map_err(|e: std::io::Error| Error::Io(e.to_string()))
}

DST library architecture

This section moves beyond just the tokio runtime into further complexity, such as testing with one clock for packet delivery, one place where faults are chosen, one network model, and one record of what happened.

Using it to test our distributed KV store

Here we get to see the blog circle back to work at SurrealDB and how this testing is being used, for example with scenarios and fault profiles and more.

// A scenario pairs a fault profile with a simulated-time budget
// and a set of invariants
struct Scenario {
    name: String,
    profile: FaultProfile,
    budget_sim_ms: u64,
    invariants: Vec<Invariant>,
}

// Example: a crash-recovery scenario described 
// without exposing the internal protocol
let scenario = Scenario {
    name: "crash_recovery".into(),
    profile: FaultProfile { /* per-tick crash / bounce / partition rates */ },
    budget_sim_ms: 30_000,
    invariants: vec![
        Invariant::CommittedNeverRegresses,
        Invariant::AllUpNodesNormalAtEnd,
        Invariant::ConnectedNodesAgreeOnViewAtEnd,
    ],
};

If your interest has been piqued, and try out some of the runnable scenarios! They can be run and modified all inside the blog post itself.

For discussions on testing or SurrealDB in general, feel free to drop by .

And if this is your first time encountering SurrealDB, welcome aboard! You can try it out today in your browser window via our sandbox at . If you like what you see but don't want to yet, just click on the Sign in button to create a free SurrealDB Cloud instance where the data you have been experimenting with can be saved - all it requires is an email to create the account.

Related posts

Our newsletter

Get tutorials, AI agent recipes, webinars, and early product updates in your inbox every two weeks

SurrealDB

The context layer for AI agents.

Documents, graphs, vectors, time-series, and memory.
One transaction, one query, one deployment.

Explore with AI

Stay in the loop

Tutorials, AI agent recipes, and product updates, every two weeks.

Independently verified

SOC 2 Type 2

GDPR

Cyber Essentials Plus

ISO 27001

Trust Centre

Copyright © 2026 SurrealDB Ltd. Registered in England and Wales. Company no. 13615201

Registered address: 3rd Floor 1 Ashley Road, Altrincham, Cheshire, WA14 2DT, United Kingdom

Trading address: Huckletree Oxford Circus, 213 Oxford Street, London, W1D 2LG, United Kingdom