Performance Testing Guide with Gatling¶
This guide explains how to run performance tests for the Spring Boot Circuit Breaker API using Gatling.
Table of Contents¶
- Overview
- Prerequisites
- Quick Start
- Test Scenarios
- Running Tests
- Understanding Results
- Best Practices
- Troubleshooting
Overview¶
This application includes comprehensive performance testing using Gatling, a powerful open-source load testing framework. The tests are designed to showcase various performance testing patterns for Java developers.
What is Gatling?¶
Gatling is a highly capable load testing tool written in Scala. It provides: - High Performance: Can simulate thousands of users with minimal resources - Expressive DSL: Easy-to-read test scenarios - Rich Reports: Beautiful HTML reports with detailed metrics - CI/CD Integration: Easy integration with build tools
Test Suite Overview¶
| Test | Purpose | Duration | Users | Focus |
|---|---|---|---|---|
| BasicLoadSimulation | Normal load testing | ~1 min | 45 | Basic functionality |
| StressTestSimulation | Breaking point identification | ~2 min | 200+ | High load |
| CircuitBreakerSimulation | Resilience testing | ~2 min | 60 | Circuit breaker behavior |
| EnduranceTestSimulation | Stability over time | 10 min | 32 | Memory leaks, degradation |
Prerequisites¶
Required¶
- Java 21 or higher
- Gradle 9.1.0 or higher
- Running Spring Boot application on
http://localhost:8080
Optional¶
- Docker (for containerized testing)
- 4GB+ RAM for stress tests
- MongoDB (if testing database operations)
Quick Start¶
1. Start the Application¶
# Option 1: Run locally
./gradlew bootRun
# Option 2: Run with Docker
docker-compose up -d
# Verify application is running
curl http://localhost:8080/actuator/health
2. Run Your First Performance Test¶
# Run basic load test
./gradlew gatlingRun-com.anr.performance.BasicLoadSimulation
# View results
open build/reports/gatling/basicloadsimulation-*/index.html
Test Scenarios¶
1. BasicLoadSimulation¶
Purpose: Validate basic functionality under normal load
Characteristics: - 45 concurrent users - Gradual ramp-up over 20 seconds - Tests health checks, API endpoints, and circuit breaker - Expected success rate: >95%
When to use: - Smoke testing after deployments - Baseline performance metrics - Regression testing
Run:
Expected Results: - Max response time: <5 seconds - Success rate: >95% - No circuit breaker trips
2. StressTestSimulation¶
Purpose: Identify system breaking points and limits
Characteristics: - 200+ concurrent users - Includes spike tests (100 users at once) - Sustained high load for 60 seconds - Mixed workload patterns - Expected success rate: >80%
When to use: - Capacity planning - Infrastructure sizing - Identifying bottlenecks
Run:
Expected Results: - Max response time: <10 seconds - Success rate: >80% - Circuit breaker may open under extreme load
What to watch: - Response time degradation - Error rate increase - Circuit breaker activation - Resource utilization (CPU, memory)
3. CircuitBreakerSimulation¶
Purpose: Verify Resilience4j circuit breaker behavior
Characteristics: - 60 concurrent users - Specific scenarios to trigger circuit breaker - Tests recovery patterns - Validates fail-fast behavior
Test Phases: 1. Normal Operation (0-20s): Baseline behavior 2. Trigger Circuit Breaker (20-40s): Rapid requests to open circuit 3. Recovery (40-60s): Verify half-open and closed states 4. Mixed Load (throughout): Realistic traffic patterns 5. Resilience Verification (60-90s): Post-stress validation
When to use: - Validating circuit breaker configuration - Testing failure scenarios - Verifying recovery mechanisms
Run:
Expected Results: - Success rate: >70% (accounts for circuit breaker opening) - Circuit breaker opens under stress - System recovers after load reduction - No cascading failures
Circuit Breaker States: - CLOSED: Normal operation, requests pass through - OPEN: Circuit breaker activated, requests fail fast - HALF_OPEN: Testing if service recovered
4. EnduranceTestSimulation¶
Purpose: Test stability and performance over extended periods
Characteristics: - 32 concurrent users - 10-minute duration - Sustained moderate load - Periodic burst patterns - Continuous health monitoring
When to use: - Identifying memory leaks - Testing resource cleanup - Validating long-running stability - Production readiness verification
Run:
Expected Results: - Success rate: >99% - Stable response times throughout - No memory leaks - No resource exhaustion
What to monitor: - Memory usage trends - Response time stability - Error rate consistency - JVM garbage collection
Running Tests¶
Run All Tests¶
Run Specific Test¶
# Basic load test
./gradlew gatlingRun-com.anr.performance.BasicLoadSimulation
# Stress test
./gradlew gatlingRun-com.anr.performance.StressTestSimulation
# Circuit breaker test
./gradlew gatlingRun-com.anr.performance.CircuitBreakerSimulation
# Endurance test
./gradlew gatlingRun-com.anr.performance.EnduranceTestSimulation
Run with Custom Configuration¶
# Set custom base URL
./gradlew gatlingRun -Dgatling.baseUrl=http://production-server:8080
# Increase log level
./gradlew gatlingRun -Dgatling.logLevel=DEBUG
# Custom simulation
./gradlew gatlingRun -Dgatling.simulationClass=com.anr.performance.BasicLoadSimulation
Run in CI/CD¶
# Non-interactive mode
./gradlew gatlingRun --no-daemon
# With specific assertions
./gradlew gatlingRun -Dgatling.assertions.global.successfulRequests.percent.gt=95
Understanding Results¶
Report Location¶
After running a test, reports are generated at:
Key Metrics¶
1. Response Time¶
- Mean: Average response time
- Min/Max: Fastest and slowest requests
- Percentiles:
- 50th (Median): Half of requests faster
- 75th: 75% of requests faster
- 95th: 95% of requests faster (important SLA metric)
- 99th: 99% of requests faster
2. Throughput¶
- Requests per second: Total request rate
- Responses per second: Completed requests rate
3. Success Rate¶
- OK: Successful requests (HTTP 2xx)
- KO: Failed requests (HTTP 4xx, 5xx, timeouts)
4. Active Users¶
- Concurrent virtual users over time
Reading the Report¶
Global Statistics:
================================================================================
---- Global Information --------------------------------------------------------
> request count 1000 (OK=950 KO=50 )
> min response time 12 (OK=12 KO=45 )
> max response time 2345 (OK=2345 KO=1234 )
> mean response time 234 (OK=220 KO=567 )
> std deviation 123 (OK=100 KO=234 )
> response time 50th percentile 200 (OK=195 KO=450 )
> response time 75th percentile 350 (OK=340 KO=670 )
> response time 95th percentile 890 (OK=850 KO=1100 )
> response time 99th percentile 1234 (OK=1200 KO=1234 )
> mean requests/sec 16.67 (OK=15.83 KO=0.83 )
================================================================================
What to look for: - ✅ Success rate >95% - ✅ 95th percentile <2 seconds - ✅ Mean response time <500ms - ⚠️ High standard deviation (inconsistent performance) - ❌ Increasing response times over time (degradation)
Best Practices¶
1. Test Environment¶
Do: - Use dedicated test environment - Match production configuration - Isolate from other tests - Monitor system resources
Don't: - Test against production - Run multiple tests simultaneously - Test on developer machines - Ignore system resource limits
2. Test Data¶
Do: - Use realistic data volumes - Vary input data - Clean up test data - Use CSV feeders for variety
Don't: - Use production data - Hardcode test data - Ignore data cleanup - Use same data repeatedly
3. Interpreting Results¶
Do: - Establish baselines - Compare trends over time - Consider percentiles, not just averages - Analyze failures
Don't: - Focus only on mean values - Ignore outliers - Compare different environments - Skip failure analysis
4. Performance Tuning¶
Do: - Test one change at a time - Document configuration changes - Measure before and after - Consider JVM tuning
Don't: - Make multiple changes at once - Tune without measuring - Ignore application logs - Over-optimize prematurely
Troubleshooting¶
Application Not Responding¶
Symptoms: - Connection refused errors - Timeout errors
Solutions:
# Check if application is running
curl http://localhost:8080/actuator/health
# Check application logs
docker-compose logs app
# Restart application
docker-compose restart app
High Failure Rate¶
Symptoms: - Success rate <80% - Many HTTP 503 errors
Possible Causes: 1. Circuit breaker opened (expected in stress tests) 2. Application overloaded 3. Database connection issues 4. Memory exhaustion
Solutions:
# Check circuit breaker status
curl http://localhost:8080/actuator/health
# Check memory usage
docker stats
# Increase JVM heap
JAVA_OPTS=-Xmx2g -Xms1g docker-compose up -d
Slow Response Times¶
Symptoms: - High 95th/99th percentiles - Increasing response times
Possible Causes: 1. Insufficient resources 2. Database slow queries 3. Network latency 4. GC pauses
Solutions:
# Enable GC logging
JAVA_OPTS="-Xlog:gc*:file=gc.log" ./gradlew bootRun
# Check database performance
# Monitor connection pool
# Increase resources
# Tune JVM parameters
Out of Memory¶
Symptoms: - Test crashes - OutOfMemoryError
Solutions:
# Increase Gradle heap
export GRADLE_OPTS="-Xmx2g"
# Reduce concurrent users
# Shorten test duration
# Increase application memory
Connection Timeouts¶
Symptoms: - Request timeout errors - Connection pool exhausted
Solutions:
# Increase timeout in gatling.conf
# Increase connection pool size
# Reduce concurrent users
# Add connection keep-alive
Advanced Topics¶
Custom Scenarios¶
Create your own simulation:
package com.anr.performance
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class CustomSimulation extends Simulation {
val httpProtocol = http
.baseUrl("http://localhost:8080")
.basicAuth("user", "password")
val scn = scenario("Custom Test")
.exec(http("My Request").get("/api/v1/default"))
setUp(scn.inject(atOnceUsers(10))).protocols(httpProtocol)
}
Using CSV Feeders¶
val productFeeder = csv("data/products.csv").random
val scn = scenario("Product Test")
.feed(productFeeder)
.exec(http("Get Product")
.get("/api/v1/products/${name}")
)
Assertions¶
setUp(scn.inject(rampUsers(100) during (60.seconds)))
.assertions(
global.responseTime.max.lt(5000),
global.successfulRequests.percent.gt(95),
details("My Request").responseTime.percentile3.lt(2000)
)
Integration with CI/CD¶
GitHub Actions Example¶
name: Performance Tests
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
jobs:
performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
- name: Start Application
run: docker-compose up -d
- name: Wait for Application
run: sleep 30
- name: Run Performance Tests
run: ./gradlew gatlingRun
- name: Upload Reports
uses: actions/upload-artifact@v3
with:
name: gatling-reports
path: build/reports/gatling/
Resources¶
Last Updated: October 17, 2025
Gatling Version: 3.10.5
Status: ✅ Production Ready