Using LatencyLab
This is the application's own Guide, shortened.
The full version ships in the app, under the book button.
Before the six steps: what you are looking at
LatencyLab is a design-time latency simulator. You describe an architecture, planned or existing, as a small explicit model: the units of work, the events that trigger them and the shared resources they queue behind. A model is your architecture written down small enough to argue about; you are not modelling your code, you are modelling the shape of the design. Models are plain JSON and the composer builds them without hand-writing any.
Running the model executes it as a simulation, hundreds or thousands of times, each run seeded so the whole experiment is reproducible. For every run it records the makespan (how long the whole flow took, which is how long the user waited) and the critical path (the chain of tasks and waits that prevented the run finishing sooner). Because it works on the design rather than the code, it applies to any event-driven software: web backends, desktop and mobile UIs, microservices and embedded pipelines.
Your first run, in six steps
- Examples menu, then Checkout. Run flashes twice to say it is ready.
- Leave Runs at 200 and Seed at 1.
- Press Run.
- Read Summary: the percentiles of the makespan, which is how long the whole piece of work took.
- Read Critical path: the chain of work that actually held the run up.
- Press the application mark in the middle of the toolbar for Distributions, then look at the shape rather than any one number.
That is the whole loop. Everything else is a variation on it.
What the three panels mean
- Makespan distribution. A shape, not a target. A single run is not representative of anything; the spread is the finding.
- Critical path. Not what was slow. It is the chain that prevented progress in that run. Expensive work off the path delayed nobody.
- Critical-path frequency. How often each chain was the one holding things up. A path that dominates is a behavioural mode, the only kind worth designing against.
Change one thing, run it again
- Press Edit. The composer opens with the loaded model already in it.
- Change one thing. Raising a context's concurrency from 1 to 2 is the clearest first experiment.
- Export + Load Into Main UI, then Run again with the same seed.
- Compare the percentiles and the dominant path against what you had.
One change at a time. Two changes and a different answer tells you nothing about which one did it.
Writing a model from nothing
Press Compose and work down the four parts in order, because each uses the one before it.
- System names the model and sets the entry event, which starts a run.
- Contexts are what work runs on: a thread pool, a database, a browser main thread. Their only setting is concurrency, which is where queueing comes from.
- Tasks are units of work: the context they run in, how long they take as a distribution and the events they emit.
- Wiring connects events to tasks, optionally after a delay. Wiring is where the structure lives, so it is the part worth arguing about.
Then Validate and Export when it says so.
Choosing the settings
- Runs. 200 is enough to see the shape and compare two structures. To say anything about p99, think in thousands.
- Seed. Same model and seed, same answer, every time. Hold it steady to compare structures, then change it to check the difference was not one lucky draw.
- Concurrency. The number of things that genuinely happen at once. A concurrency of 1 serialises everything sent to it, which is what a single database connection or UI thread actually is.
- Distribution. Fixed only when the duration truly does not vary. Normal for work that varies symmetrically. Lognormal for IO, network or contention: choosing normal there is how a model comes out far too optimistic at p99.
- Delays on wiring. Debounces, retry backoffs, poll intervals. Model them: they frequently own the median while everyone is looking at the database.
- Stress multiplier. Every duration multiplied, so you can ask what happens when everything is twice as slow.
Reading the answer honestly
- Name the dominant behaviour before proposing any fix. A task that never appears on a dominant path changes nothing when you speed it up.
- Percentiles describe exposure, not goals. Lowering one without understanding the shape moves the cost rather than removing it.
- LatencyLab tells you what a model does, not whether the model is right. It makes an argument checkable; it does not spare you having one.
Where to next
Every page answers one question.