Kurtosis Architecture
Background
Every test in existence goes through four phases:
- Setup
- Perturbation
- Validation
- Teardown
In unit testing, this usually looks like:
- Instantiate the object to test and mock all surrounding objects
- Execute the functions being tested
- Assert the expected result
- Garbage collect all objects
Engineers have well-established unit-testing tools for each phase, so developers write many.
When the component being tested is the entire distributed system however, things become seriously difficult: where do we run the test nodes? How do we initialize their config & data files? Where do we run the test logic, and how does it talk to the system? How do we ensure the network is cleaned up after the test is done?
These are challenging questions, and in our experience teams tend to go one of two ways: write their own automation framework from scratch, or skip sandboxed networks altogether and run a single long-lived testnet that everyone uses. The latter is error-prone and costly to maintain while the former is bespoke and costly to write. Ideally, teams would have a platform that automates the heavy lifting of each phase so they can focus on writing tests. This is Kurtosis.
Architecture
To see how Kurtosis resolves the distributed system testing challenges, here’s an example diagram of a Kurtosis testsuite for Microservice X that contains two tests:

This architecture has the following components:
- Testnet: The network of services being tested (one per test)
- Service: A Dockerized service forming part of a testnet
- Kurtosis CLI: The CLI that coordinates the execution of a testsuite, and the entrypoint for running Kurtosis
- Kurtosis API: The Docker sidecar container (one per test) that handles initializing, manipulating, and tearing down testnets
- Testsuite: The Docker container (one per test) that holds the user’s custom logic for starting the custom services forming the networks being tested, as well as the logic for the tests to run
- Kurtosis Client: A library in the user’s language of choice that abstracts away communication with the Kurtosis API for testnet initialization, manipulation, and teardown
The test phases proceed in the following order for each test:
- Setup:
- The CLI creates a new Docker subnet to contain the Kurtosis API container, testsuite container, and testnet services
- The API container and testsuite containers are launched
- As part of launch, the Kurtosis client library instructs the API container what the testnet looks like
- The API container instantiates the testnet as instructed
- Perturbation: The test, running inside the testsuite container, makes calls against the network
- Validation: The test asserts the expected responses
- Teardown:
- The test completes and reports its status back to the CLI
- The API container stops the testnet containers
- The API container and testsuite container exit
- The CLI tears down the Docker subnet created for the test
Key features:
- Testnet services run in Docker containers, so any Dockerized service can be used in a testnet (e.g. Test 1 in the diagram above uses an Oracle database alongside Microservice X)
- Each test receives its own independent testnet running in an isolated Docker subnet, so tests are consistently repeatable and don’t interfere with each other
- Testsuites run as Docker containers, so developers can write tests in any language they please
- The Kurtosis client library and API container automate the gruntwork of network setup, manipulation, and teardown so tests are easy to write
Back to index