Squashing the Heisenbug with Deterministic Simulation Testing by Dominik Tornow

ScyllaDB 0 views 46 slides Oct 09, 2025
Slide 1
Slide 1 of 46
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46

About This Presentation

Distributed systems are hard to test, with bugs that are difficult to reproduce and diagnose. This talk introduces Deterministic Simulation Testing, a technique that removes non-determinism to enable exhaustive, reproducible tests. We’ll walk through building a custom simulator, from controlling t...


Slide Content

A ScyllaDB
Community
Squashing the Heisenbug
Dominik Tornow
CEO

Resonate HQ
Dominik Tornow
CEO at Resonate HQ
■Focus on concurrent, distributed systems
■Software Engineer by day
■Author by night

Complex Problems. Simple Code.
Rest in Peace

Distributed Async Await
A language integrated programming model for
concurrent, distributed applications

Concurrency
Non-deterministic partial order
Distribution
Non-deterministic partial failure

P = a • b • c
Q = x • y • z

Sequential Composition
P ; Q

a • b • c • x • y • z

Concurrent Composition
P | Q

a • b • c • x • y • z
a • b • x • c • y • z
a • b • x • y • c • z
a • b • x • y • z • c
a • x • b • c • y • z
a • x • b • y • c • z
a • x • b • y • z • c
a • x • y • b • c • z
a • x • y • b • z • c
a • x • y • z • b • c
x • a • b • c • y • z
x • a • b • y • c • z
x • a • b • y • z • c
x • a • y • b • c • z
x • a • y • b • z • c
x • a • y • z • b • c
x • y • a • b • c • z
x • y • a • b • z • c
x • y • a • z • b • c
x • y • z • a • b • c

Distributed Composition
P | Q | ⊥

a • ⊥
x • ⊥
a • b • ⊥
a • x • ⊥
x • a • ⊥
x • y • ⊥
a • b • c • ⊥
a • b • x • ⊥
a • x • b • ⊥
a • x • y • ⊥
x • a • b • ⊥
x • a • y • ⊥
x • y • a • ⊥
x • y • z • ⊥
a • b • c • x • ⊥
a • b • x • c • ⊥
a • b • x • y • ⊥
a • x • b • c • ⊥
a • x • b • y • ⊥
a • x • y • b • ⊥
a • x • y • z • ⊥
x • a • b • c • ⊥
x • a • b • y • ⊥
x • a • y • b • ⊥
x • a • y • z • ⊥
x • y • a • b • ⊥
x • y • a • z • ⊥
x • y • z • a • ⊥
a • b • c • x • y • ⊥
a • b • x • c • y • ⊥
a • b • x • y • c • ⊥
a • b • x • y • z • ⊥
a • x • b • c • y • ⊥
a • x • b • y • c • ⊥
a • x • b • y • z • ⊥
a • x • y • b • c • ⊥
a • x • y • b • z • ⊥
a • x • y • z • b • ⊥
x • a • b • c • y • ⊥
x • a • b • y • c • ⊥
x • a • b • y • z • ⊥
x • a • y • b • c • ⊥
x • a • y • b • z • ⊥
x • a • y • z • b • ⊥
x • y • a • b • c • ⊥
x • y • a • b • z • ⊥
x • y • a • z • b • ⊥
x • y • z • a • b • ⊥
a • b • c • x • y • z
a • b • x • c • y • z
a • b • x • y • c • z
a • b • x • y • z • c
a • x • b • c • y • z
a • x • b • y • c • z
a • x • b • y • z • c
a • x • y • b • c • z
a • x • y • b • z • c
a • x • y • z • b • c
x • a • b • c • y • z
x • a • b • y • c • z
x • a • b • y • z • c
x • a • y • b • c • z
x • a • y • b • z • c
x • a • y • z • b • c
x • y • a • b • c • z
x • y • a • b • z • c
x • y • a • z • b • c
x • y • z • a • b • c

a • ⊥
x • ⊥
a • b • ⊥
a • x • ⊥
x • a • ⊥
x • y • ⊥
a • b • c • ⊥
a • b • x • ⊥
a • x • b • ⊥
a • x • y • ⊥
x • a • b • ⊥
x • a • y • ⊥
x • y • a • ⊥
x • y • z • ⊥
a • b • c • x • ⊥
a • b • x • c • ⊥
a • b • x • y • ⊥
a • x • b • c • ⊥
a • x • b • y • ⊥
a • x • y • b • ⊥
a • x • y • z • ⊥
x • a • b • c • ⊥
x • a • b • y • ⊥
x • a • y • b • ⊥
x • a • y • z • ⊥
x • y • a • b • ⊥
x • y • a • z • ⊥
x • y • z • a • ⊥
a • b • c • x • y • ⊥
a • b • x • c • y • ⊥
a • b • x • y • c • ⊥
a • b • x • y • z • ⊥
a • x • b • c • y • ⊥
a • x • b • y • c • ⊥
a • x • b • y • z • ⊥
a • x • y • b • c • ⊥
a • x • y • b • z • ⊥
a • x • y • z • b • ⊥
x • a • b • c • y • ⊥
x • a • b • y • c • ⊥
x • a • b • y • z • ⊥
x • a • y • b • c • ⊥
x • a • y • b • z • ⊥
x • a • y • z • b • ⊥
x • y • a • b • c • ⊥
x • y • a • b • z • ⊥
x • y • a • z • b • ⊥
x • y • z • a • b • ⊥
a • b • c • x • y • z
a • b • x • c • y • z
a • b • x • y • c • z
a • b • x • y • z • c
a • x • b • c • y • z
a • x • b • y • c • z
a • x • b • y • z • c
a • x • y • b • c • z
a • x • y • b • z • c
a • x • y • z • b • c
x • a • b • c • y • z
x • a • b • y • c • z
x • a • b • y • z • c
x • a • y • b • c • z
x • a • y • b • z • c
x • a • y • z • b • c
x • y • a • b • c • z
x • y • a • b • z • c
x • y • a • z • b • c
x • y • z • a • b • c
!
!
!

Software Systems
Thinking about Correctness

Specification
Implementation

Software Verification
aims to proof
all traces are within the specification
Software Testing
aims to find
some traces are outside the specification

Software Verification
Will prove the absence of bugs
Software Testing
Can prove the presence of bugs

Software Testing
Thinking about Deterministic Simulation Testing

Increase number
of distinct traces
Increase length
of distinct traces
Ensure reproducibility
of distinct traces

System

SystemApplicationEnvironmentState State

ApplicationEnvironmentState StateAPISimulator

ApplicationSimulatorState StateAPI
The trace is determined by
the initial state of the simulator and the initial state of the system

Simulator
Seed
Simulator
Step
Simulator
Next State
Input
Application
Init State
Application
Step
Application
Next State
Input
Simulator
Step
Simulator
Next State
Application
Step
Application
Next State

Deterministic Simulation Testing
Distributed Async Await

Server Worker1
Worker2 Worker3
Worker4 Worker5
Network

Server Worker1
Worker2 Worker3
Worker4 Worker5
NetworkSimulator

const simulator = new Simulator(options);
simulator.register(new WorkerProcess("worker-1", "default"));
simulator.register(new WorkerProcess("worker-2", "default"));
simulator.register(new ServerProcess("server"));

Simulator.send(
Message.Request(unicast(“user"), unicast("server"), {
...
param: { func: "fibonacci", args: [10] }
...
})
);

{
seed: 21, // Random Seed
delay: 0.75, // Message Delay
dropProb: 0.25, // Message Drop
duplProb: 0.25, // Message Duplication
flipProb: 0.25 // Message Modification
}

{
“params”: {
“func”: “factorial”
}
}

{
“params”: {
“func”: “factorial”
}
}
invalid format

{
“params”: {
“func”: “factorial”
}
}
valid format, invalid schema

{
“params”: {
“func”: “factorial”
}
}
valid format, valid schema, invalid payload

export interface Network {
send(req: Req, callback: (timeout: boolean, res: Res) => void): void;
recv(msg: Msg): void;
}

git clone https://github.com/resonatehq/resonate-sdk-ts.git

Conclusion
Deterministic Simulation Testing

Correct programs are more elegant than incorrect ones
Barton P. Miller

Thank you! Let’s connect.
Dominik Tornow
[email protected]
@DominikTornow
https://resonatehq.io
Resonate HQ
Tags