cassandra-easy-stress is a powerful and flexible tool for performing benchmarks and testing data models for Apache Cassandra.
Most benchmarking tools require learning complex configuration systems before you can run your first test. cassandra-easy-stress provides pre-built workloads for common Cassandra patterns. Modify these workloads with flexible parameters to match your environment, or write custom workloads in Kotlin when you need full control.
Full docs are here: https://apache.github.io/cassandra-easy-stress/
The easiest way to get started on Linux is to use system packages. Instructions for installation can be found here: https://apache.github.io/cassandra-easy-stress/#_installation
Clone this repo, then build with gradle:
git clone https://github.com/apache/cassandra-easy-stress.git
cd cassandra-easy-stress
./gradlew shadowJar
Use the shell script wrapper to start and get help:
bin/cassandra-easy-stress -h
Time series workload with a billion operations:
bin/cassandra-easy-stress run BasicTimeSeries -i 1B
Key value workload with a million operations across 5k partitions, 50:50 read:write ratio:
bin/cassandra-easy-stress run KeyValue -i 1M -p 5k -r .5
Time series workload, using TWCS:
bin/cassandra-easy-stress run BasicTimeSeries -i 10M --compaction "{'class':'TimeWindowCompactionStrategy', 'compaction_window_size': 1, 'compaction_window_unit': 'DAYS'}"
Time series workload with a run lasting 1h and 30mins:
bin/cassandra-easy-stress run BasicTimeSeries -d "1h30m"
Time series workload with Cassandra Authentication enabled:
bin/cassandra-easy-stress run BasicTimeSeries -d '30m' -U '<username>' -P '<password>'
**Note**: The quotes are mandatory around the username/password
if they contain special chararacters, which is pretty common for password
Docs are served out of /docs and can be rebuild using ./gradlew docs.
Run all tests against the default version (Cassandra 5.0):
./gradlew testRun tests against a specific version:
./gradlew test40 # Cassandra 4.0
./gradlew test41 # Cassandra 4.1
./gradlew test50 # Cassandra 5.0Run tests against all versions sequentially:
./gradlew testAllVersionsAll integration tests use Testcontainers to automatically manage Cassandra instances. This means:
- No manual setup required: Docker is the only prerequisite
- Isolated test environments: Each test class gets a fresh Cassandra container
- Automatic cleanup: Containers are stopped and removed after tests complete
- Version flexibility: Different Cassandra versions can be tested without installing anything
When a test class extends CassandraTestBase, the framework automatically:
- Detects the
CASSANDRA_VERSIONenvironment variable (defaults to "5.0") - Builds a Docker image from the corresponding Dockerfile in
docker/cassandra-{version}/ - Starts a Cassandra container and waits for it to be ready
- Establishes a CQL session with appropriate timeouts for testing
- Cleans up and stops the container when tests finish
Each Cassandra version uses a custom Dockerfile that enables experimental features:
- Materialized Views: Enabled via
materialized_views_enabled: true - Increased Timeouts: Higher read/write/range timeouts for test stability
- Memory Configuration: Conservative heap settings suitable for containers
The Dockerfiles are located at:
docker/cassandra-4.0/Dockerfiledocker/cassandra-4.1/Dockerfiledocker/cassandra-5.0/Dockerfile
Some workloads require specific Cassandra versions or features. Annotations control when workloads are tested.
Marks workloads that require a minimum Cassandra version. Tests automatically skip these workloads on older versions.
Example:
@MinimumVersion("5.0")
class SAI : IStressWorkload {
// SAI indexes are only available in Cassandra 5.0+
}How it works:
- The
CASSANDRA_VERSIONenvironment variable determines which version is running Workload.getWorkloadsForTesting()filters out workloads where the version doesn't meet the minimum- Version comparison supports point releases: "5.0", "5.1", etc.
Currently annotated workloads:
MaterializedViews- Requires 5.0+ (materialized views enabled)SAI- Requires 5.0+ (Storage Attached Indexes)
Marks workloads that require DataStax Enterprise features. These are skipped by default.
Example:
@RequireDSE
class DSESearch : IStressWorkload {
// Uses DSE Search (Solr) functionality
}Enable in tests:
TEST_DSE=1 ./gradlew testCurrently annotated workloads:
DSESearch- Uses DSE Search (Solr)
Marks workloads that use Accord transaction features (available in Cassandra 6.0+). These are skipped by default.
Example:
@RequireAccord
class TxnCounter : IStressWorkload {
// Uses Accord transactions
}Enable in tests:
TEST_ACCORD=1 ./gradlew testCurrently annotated workloads:
TxnCounter- Uses Accord transactions
To run all tests including DSE and Accord workloads:
TEST_DSE=1 TEST_ACCORD=1 ./gradlew testIndividual test tasks are created for each Cassandra version:
./gradlew test40 # Cassandra 4.0
./gradlew test41 # Cassandra 4.1
./gradlew test50 # Cassandra 5.0These are proper Gradle Test tasks, so they support all standard Test task options:
# Run only specific tests
./gradlew test50 --tests "*KeyValue*"
# Enable debug mode
./gradlew test50 --debug-jvm
# Rerun even if up-to-date
./gradlew test40 --rerun-tasksHow they work:
- Each task sets
CASSANDRA_VERSIONenvironment variable to the corresponding version - Uses the same test sources and classpath as the main
testtask - Integrates with Gradle's task graph for proper caching and dependency management
Runs tests against all Cassandra versions sequentially:
./gradlew testAllVersionsThis task:
- Depends on
test40,test41, andtest50 - Enforces sequential execution using
mustRunAfterto prevent Docker resource conflicts - Stops on the first failure and reports which version failed
- Displays a summary of all test results
Execution time:
- With cached Docker images: ~15-25 minutes total
The standard test task respects the CASSANDRA_VERSION environment variable:
# Test against Cassandra 4.1
CASSANDRA_VERSION=4.1 ./gradlew test
# Test against Cassandra 5.0 (default)
CASSANDRA_VERSION=5.0 ./gradlew testIf CASSANDRA_VERSION is not set, it defaults to "5.0".
The GitHub Actions CI workflow (.github/workflows/ci.yml) runs on every push and pull request.
Test matrix:
- Java versions: 17 and 21
- Cassandra versions: 4.0, 4.1, 5.0
This creates 6 test jobs total:
- Cassandra 4.0 on Java 17 and 21
- Cassandra 4.1 on Java 17 and 21
- Cassandra 5.0 on Java 17 and 21
Workflow steps:
- Checkout and setup: Check out code, set up JDK and Gradle
- Run tests: Execute the version-specific test task (e.g.,
./gradlew test50) - Code quality: Run ktlint and detekt checks in parallel
- Coverage: Generate code coverage reports with kover (using default test task only)
- Build: Create distribution tarball artifact (main branch only, after all checks pass)
- Artifact:
cassandra-easy-stress-{version}.tar.gz - Retention: 90 days
- Contains: binaries, all dependencies, and LICENSE
- Artifact:
Replicate CI behavior locally:
# Run the same tests as CI for Cassandra 5.0
./gradlew test50 ktlintCheck detekt
# Test all versions like CI does (sequentially)
./gradlew testAllVersions
# Generate coverage report
./gradlew test koverXmlReportIntegration tests extend CassandraTestBase:
class MyWorkloadTest : CassandraTestBase() {
@Test
fun testWorkload() {
// connection is available from CassandraTestBase
val result = connection.execute("SELECT * FROM system.local")
assertThat(result).isNotNull
}
}Available properties from CassandraTestBase:
connection: CqlSession instanceip: Container IP addressport: Mapped CQL portlocalDc: Datacenter name (defaults to "datacenter1")
Utility methods:
cleanupKeyspace(): Drops the test keyspacekeyspaceExists(): Checks if test keyspace existsgetCassandraVersion(): Returns Cassandra release version string
Test guidelines:
- Use
CassandraTestBasefor integration tests requiring Cassandra - Use
@BeforeEachto ensure clean state withcleanupKeyspace() - Use AssertJ assertions for clear, fluent test assertions
- Test against multiple versions if workload behavior varies by version
- Don't use
runBlockingin tests (usekotlinx.coroutines.test.runTestinstead)
cassandra-easy-stress includes a Model Context Protocol (MCP) server that allows AI assistants to interact with the stress testing tool. To start in server mode:
cassandra-easy-stress server
To test the MCP server integration with Claude Code:
-
Add the MCP server (assuming it's running locally):
claude mcp add -t sse cassandra-easy-stress http://localhost:9000/sse
-
Run the MCP integration test prompt:
/test-mcp
This will verify that the MCP server is properly configured and accessible from Claude Code.
The MCP server should work with any tool that supports the Model Context Protocol. If you've successfully integrated cassandra-easy-stress with another MCP-compatible tool, please send a PR with instructions and we'll update this README.