Open source, high-concurrency load testing framework built on Java 21. Achieve 10,000+ TPS with minimal memory footprint using Project Loom's virtual threads. Released under Apache License 2.0.
@VirtualThreads
public class HttpLoadTest implements Task {
private HttpClient client;
@Override
public void setup() {
client = HttpClient.newBuilder()
.executor(Executors.newVirtualThreadPerTaskExecutor())
.build();
}
@Override
public TaskResult execute() {
var response = client.send(request, ...);
return TaskResult.success(response.body());
}
}
Everything you need for modern load testing
Leverage Java 21's Project Loom for millions of concurrent operations with minimal memory overhead. Perfect for I/O-bound load tests.
Six built-in patterns: Static, Ramp-up, Ramp-sustain, Step, Spike, and Sine wave. Model any real-world traffic scenario.
Micrometer-based metrics with percentile calculations. Export to OpenTelemetry, console, or custom backends.
Just implement the Task interface with setup(), execute(), and cleanup(). The framework handles the rest.
Choose virtual threads for I/O-bound tasks or platform threads for CPU-intensive workloads. Annotate and go.
10,000+ TPS per worker, millions of concurrent requests, all with minimal resource consumption.
Built for the modern Java ecosystem
Built exclusively for Java 21, leveraging records, sealed types, pattern matching, and virtual threads. No legacy baggage.
Core API has zero dependencies. Full framework weighs in at just ~1.6MB. Every dependency is justified and minimal.
Comprehensive test coverage (โฅ90%), OpenTelemetry integration, and battle-tested patterns. Ready for production workloads.
Simple, intuitive API. Clear documentation. Working examples. Get started in minutes, not hours.
See how easy it is to get started
import com.vajrapulse.api.*;
@VirtualThreads // Use virtual threads for I/O
public class HttpLoadTest implements Task {
private HttpClient client;
private HttpRequest request;
@Override
public void setup() throws Exception {
client = HttpClient.newBuilder()
.executor(Executors.newVirtualThreadPerTaskExecutor())
.connectTimeout(Duration.ofSeconds(10))
.build();
request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/endpoint"))
.timeout(Duration.ofSeconds(10))
.GET()
.build();
}
@Override
public TaskResult execute() throws Exception {
HttpResponse response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
if (response.statusCode() == 200) {
return TaskResult.success(response.body());
} else {
return TaskResult.failure(
new RuntimeException("HTTP " + response.statusCode())
);
}
}
@Override
public void cleanup() throws Exception {
// Cleanup resources if needed
}
}
import com.vajrapulse.api.*;
import java.time.Duration;
// Static: Constant TPS
LoadPattern staticPattern = new StaticLoad(
100.0,
Duration.ofMinutes(5)
);
// Ramp-up: Linear increase from 0 to max
LoadPattern rampPattern = new RampUpLoad(
500.0,
Duration.ofSeconds(30)
);
// Ramp-sustain: Ramp then maintain
LoadPattern rampSustain = new RampUpToMaxLoad(
500.0,
Duration.ofSeconds(30), // ramp duration
Duration.ofMinutes(5) // total duration
);
// Step: Discrete phases
LoadPattern stepPattern = new StepLoad(List.of(
new StepLoad.Step(50.0, Duration.ofSeconds(30)),
new StepLoad.Step(200.0, Duration.ofMinutes(1)),
new StepLoad.Step(500.0, Duration.ofMinutes(2))
));
// Sine: Smooth oscillation
LoadPattern sinePattern = new SineWaveLoad(
300.0, // mean rate
150.0, // amplitude
Duration.ofMinutes(3), // total duration
Duration.ofSeconds(20) // period
);
// Spike: Periodic bursts
LoadPattern spikePattern = new SpikeLoad(
200.0, // base rate
800.0, // spike rate
Duration.ofMinutes(2), // total duration
Duration.ofSeconds(15), // spike interval
Duration.ofSeconds(3) // spike duration
);
import com.vajrapulse.api.*;
import com.vajrapulse.core.metrics.AggregatedMetrics;
import com.vajrapulse.exporter.console.ConsoleMetricsExporter;
import com.vajrapulse.worker.pipeline.MetricsPipeline;
import java.time.Duration;
public class LoadTestRunner {
public static void main(String[] args) throws Exception {
// Create your task
HttpLoadTest task = new HttpLoadTest();
// Define load pattern
LoadPattern pattern = new StaticLoad(
100.0,
Duration.ofSeconds(30)
);
// Build metrics pipeline with exporters
try (MetricsPipeline pipeline = MetricsPipeline.builder()
.addExporter(new ConsoleMetricsExporter())
.withPeriodic(Duration.ofSeconds(5)) // Live updates
.withPercentiles(0.5, 0.95, 0.99)
.build()) {
// Run the test
pipeline.run(task, pattern);
}
// Automatic cleanup
}
}
# Static pattern
java -jar vajrapulse-worker-all.jar \
com.example.HttpLoadTest \
--mode static \
--tps 100 \
--duration 5m
# Ramp-up pattern
java -jar vajrapulse-worker-all.jar \
com.example.HttpLoadTest \
--mode ramp \
--tps 200 \
--ramp-duration 30s
# Ramp-sustain pattern
java -jar vajrapulse-worker-all.jar \
com.example.HttpLoadTest \
--mode ramp-sustain \
--tps 200 \
--ramp-duration 30s \
--duration 5m
# Step pattern
java -jar vajrapulse-worker-all.jar \
com.example.HttpLoadTest \
--mode step \
--steps "50@30s,200@1m,500@2m,100@30s"
# Sine wave pattern
java -jar vajrapulse-worker-all.jar \
com.example.HttpLoadTest \
--mode sine \
--mean-rate 300 \
--amplitude 150 \
--period 120s \
--duration 15m
# Spike pattern
java -jar vajrapulse-worker-all.jar \
com.example.HttpLoadTest \
--mode spike \
--base-rate 100 \
--spike-rate 800 \
--spike-interval 60s \
--spike-duration 5s \
--duration 10m
Add VajraPulse to your project in minutes
dependencies {
// Import BOM
implementation(platform("com.vajrapulse:vajrapulse-bom:0.9.3"))
// Use modules without versions
implementation("com.vajrapulse:vajrapulse-core")
implementation("com.vajrapulse:vajrapulse-worker")
// Optional exporters
implementation("com.vajrapulse:vajrapulse-exporter-console")
implementation("com.vajrapulse:vajrapulse-exporter-opentelemetry")
}
dependencies {
// Import BOM
implementation platform('com.vajrapulse:vajrapulse-bom:0.9.3')
// Use modules without versions
implementation 'com.vajrapulse:vajrapulse-core'
implementation 'com.vajrapulse:vajrapulse-worker'
// Optional exporters
implementation 'com.vajrapulse:vajrapulse-exporter-console'
implementation 'com.vajrapulse:vajrapulse-exporter-opentelemetry'
}
<dependencyManagement>
<dependencies>
<!-- Import BOM -->
<dependency>
<groupId>com.vajrapulse</groupId>
<artifactId>vajrapulse-bom</artifactId>
<version>0.9.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Use modules without versions -->
<dependency>
<groupId>com.vajrapulse</groupId>
<artifactId>vajrapulse-core</artifactId>
</dependency>
<dependency>
<groupId>com.vajrapulse</groupId>
<artifactId>vajrapulse-worker</artifactId>
</dependency>
</dependencies>
VajraPulse is completely open source and free to use. Released under the Apache License 2.0, you can use it in commercial and personal projects without restrictions.
Permissive open source license that allows you to:
VajraPulse is built by the community, for the community. Contributions are welcome!