Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Expert skill for Gatling simulation development, load test execution, and performance analysis. Write Gatling simulations in Scala DSL, configure injection profiles and feeders, define assertions, analyze HTML reports, and integrate with Gatling Enterprise.
.claude/skills/a5c-ai-gatling-load-testing/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 182% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 146% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 250% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 182% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 173% | 0% |
You are gatling-load-testing - a specialized skill for Gatling load test development and performance analysis. This skill provides expert capabilities for building comprehensive load testing suites using Gatling's powerful Scala DSL.
This skill enables AI-powered load testing operations including:
Write comprehensive Gatling simulations:
scalapackage simulations import io.gatling.core.Predef._ import io.gatling.http.Predef._ import scala.concurrent.duration._ class ApiLoadSimulation extends Simulation { // HTTP Protocol Configuration val httpProtocol = http .baseUrl("https://api.example.com") .acceptHeader("application/json") .contentTypeHeader("application/json") .userAgentHeader("Gatling/LoadTest") .shareConnections .maxConnectionsPerHost(10) // Test Data Feeder val userFeeder = csv("users.csv").circular val searchFeeder = jsonFile("searches.json").random // Request Chains val authenticate = exec( http("Authenticate") .post("/auth/login") .body(StringBody("""{"username":"${username}","password":"${password}"}""")) .check( status.is(200), jsonPath("$.token").saveAs("authToken"), responseTimeInMillis.lte(500) ) ) val searchProducts = exec( http("Search Products") .get("/products/search") .queryParam("q", "${searchTerm}") .header("Authorization", "Bearer ${authToken}") .check( status.is(200), jsonPath("$.results[*]").count.gte(1), responseTimeInMillis.lte(1000) ) ) val viewProduct = exec( http("View Product") .get("/products/${productId}") .header("Authorization", "Bearer ${authToken}") .check( status.is(200), jsonPath("$.id").is("${productId}"), responseTimeInMillis.lte(300) ) ) // Scenario Definition val userJourney = scenario("User Journey") .feed(userFeeder) .exec(authenticate) .pause(1, 3) .feed(searchFeeder) .exec(searchProducts) .pause(500.milliseconds, 2.seconds) .repeat(3) { exec(viewProduct) .pause(1, 2) } // Load Profile setUp( userJourney.inject( rampUsers(100).during(60.seconds), constantUsersPerSec(50).during(300.seconds), rampUsersPerSec(50).to(100).during(120.seconds) ) ).protocols(httpProtocol) .assertions( global.responseTime.percentile3.lt(1000), global.successfulRequests.percent.gte(99), forAll.failedRequests.percent.lt(1) ) }
Configure various load patterns:
scala// Ramp-up load pattern setUp( scenario.inject( rampUsers(1000).during(10.minutes) ) ) // Constant load with warm-up setUp( scenario.inject( nothingFor(5.seconds), atOnceUsers(10), rampUsers(100).during(1.minute), constantUsersPerSec(50).during(5.minutes) ) ) // Stress test pattern setUp( scenario.inject( incrementUsersPerSec(10) .times(5) .eachLevelLasting(2.minutes) .separatedByRampsLasting(30.seconds) .startingFrom(10) ) ) // Spike test pattern setUp( scenario.inject( constantUsersPerSec(20).during(2.minutes), stressPeakUsers(500).during(30.seconds), constantUsersPerSec(20).during(2.minutes) ) ) // Soak/Endurance test setUp( scenario.inject( rampUsersPerSec(1).to(30).during(5.minutes), constantUsersPerSec(30).during(4.hours) ) )
Manage test data effectively:
scala// CSV Feeder val csvFeeder = csv("data/users.csv").circular // JSON Feeder val jsonFeeder = jsonFile("data/products.json").random // JDBC Feeder val jdbcFeeder = jdbcFeeder( "jdbc:postgresql://localhost:5432/testdb", "postgres", "password", "SELECT id, email FROM users WHERE active = true" ) // Custom Feeder val customFeeder = Iterator.continually(Map( "orderId" -> java.util.UUID.randomUUID().toString, "timestamp" -> System.currentTimeMillis(), "amount" -> (100 + scala.util.Random.nextInt(900)) )) // Batch Feeder with transformation val transformedFeeder = csv("data/raw.csv") .transform { case (key, value) => if (key == "amount") (value.toDouble * 1.1).toString else value } .batch(100) .random
Handle dynamic values and session state:
scala// Extract and reuse values exec( http("Get CSRF Token") .get("/form") .check( css("input[name='csrf']", "value").saveAs("csrfToken") ) ) .exec( http("Submit Form") .post("/submit") .formParam("csrf", "${csrfToken}") .formParam("data", "${userData}") ) // JSON path extraction exec( http("Get Order") .get("/orders/${orderId}") .check( jsonPath("$.items[*].id").findAll.saveAs("itemIds"), jsonPath("$.total").saveAs("orderTotal") ) ) .foreach("${itemIds}", "itemId") { exec( http("Get Item Details") .get("/items/${itemId}") ) } // Conditional execution exec(session => { if (session("userType").as[String] == "premium") { session.set("rateLimit", 1000) } else { session.set("rateLimit", 100) } }) .doIf("${userType}", "premium") { exec(premiumFeatures) }
Define comprehensive assertions:
scalasetUp(scenario.inject(/* ... */)) .protocols(httpProtocol) .assertions( // Global assertions global.responseTime.max.lt(5000), global.responseTime.mean.lt(500), global.responseTime.percentile1.lt(200), // P50 global.responseTime.percentile2.lt(500), // P75 global.responseTime.percentile3.lt(1000), // P95 global.responseTime.percentile4.lt(2000), // P99 // Success rate assertions global.successfulRequests.percent.gte(99.5), global.failedRequests.count.lt(100), // Request-specific assertions details("Authenticate").responseTime.percentile3.lt(500), details("Search Products").successfulRequests.percent.gte(99), // Throughput assertions global.requestsPerSec.gte(1000) )
Analyze Gatling HTML reports:
scala// Report configuration .protocols(httpProtocol) .pauses(constantPauses) // Custom report naming System.setProperty("gatling.core.outputDirectoryBaseName", "api-load-test") System.setProperty("gatling.charting.indicators.lowerBound", "800") System.setProperty("gatling.charting.indicators.higherBound", "1200")
Key metrics to analyze:
This skill can leverage the following MCP servers:
| Server | Description | Use Case | |--------|-------------|----------| | locust-mcp | Load testing MCP | Alternative load testing execution | | playwright-mcp | Browser automation | UI-based load testing scenarios |
shareConnectionsThis skill integrates with the following processes:
load-testing-framework-setup.js - Initial Gatling setupload-test-execution.js - Test execution and orchestrationstress-testing-analysis.js - Stress test scenario designWhen executing operations, provide structured output:
json{ "operation": "run-simulation", "status": "completed", "simulation": { "name": "ApiLoadSimulation", "duration": "300s", "totalUsers": 5000 }, "results": { "requestCount": 150000, "errorCount": 45, "errorRate": "0.03%", "responseTime": { "mean": 245, "p50": 180, "p75": 320, "p95": 890, "p99": 1450, "max": 4200 }, "throughput": 500.5 }, "assertions": { "passed": 8, "failed": 0 }, "reportPath": "target/gatling/apisimulation-20260124/index.html" }
| Error | Cause | Resolution | |-------|-------|------------| | Connection refused | Target unavailable | Verify target URL and network | | Connection timeout | Slow target | Increase timeout, check target capacity | | OOM on injector | Too many users | Increase heap, distribute load | | Feeder exhausted | Insufficient test data | Use .circular or .random | | Session value not found | Missing extraction | Verify check expressions |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 11,245 | 13,784 | +23% | 1 | 1 | 0% | 1,893 | 5,340 | +182% | 0 | 0 | — |
case-02 | pass→pass | 10,954 | 10,238 | -7% | 1 | 1 | 0% | 1,989 | 4,902 | +146% | 0 | 0 | — |
case-03 | pass→pass | 7,886 | 11,483 | +46% | 1 | 1 | 0% | 1,354 | 4,740 | +250% | 0 | 0 | — |
case-04 | pass→pass | 10,681 | 10,892 | +2% | 1 | 1 | 0% | 1,938 | 5,465 | +182% | 0 | 0 | — |
case-05 | pass→pass | 6,820 | 6,529 | -4% | 1 | 1 | 0% | 1,461 | 3,985 | +173% | 0 | 0 | — |
case-06 | pass→pass | 12,734 | 6,650 | -48% | 1 | 1 | 0% | 2,038 | 4,323 | +112% | 0 | 0 | — |
case-07 | pass→pass | 6,147 | 6,959 | +13% | 1 | 1 | 0% | 1,357 | 4,137 | +205% | 0 | 0 | — |
case-08 | pass→pass | 10,729 | 11,812 | +10% | 1 | 1 | 0% | 1,723 | 4,879 | +183% | 0 | 0 | — |
case-09 | pass→pass | 9,527 | 6,961 | -27% | 1 | 1 | 0% | 1,551 | 4,449 | +187% | 0 | 0 | — |
case-10 | pass→pass | 12,962 | 14,023 | +8% | 1 | 1 | 0% | 2,037 | 5,823 | +186% | 0 | 0 | — |
case-11 | pass→pass | 7,604 | 11,438 | +50% | 1 | 1 | 0% | 1,346 | 4,860 | +261% | 0 | 0 | — |
case-12 | pass→pass | 11,699 | 8,295 | -29% | 1 | 1 | 0% | 2,504 | 4,670 | +87% | 0 | 0 | — |
case-13 | pass→pass | 11,639 | 5,887 | -49% | 1 | 1 | 0% | 1,872 | 4,177 | +123% | 0 | 0 | — |
case-14 | pass→pass | 10,457 | 9,714 | -7% | 1 | 1 | 0% | 1,989 | 4,837 | +143% | 0 | 0 | — |
case-15 | pass→pass | 6,068 | 1,846 | -70% | 1 | 1 | 0% | 1,018 | 3,277 | +222% | 0 | 0 | — |
case-16 | pass→pass | 16,405 | 7,159 | -56% | 1 | 1 | 0% | 2,974 | 4,448 | +50% | 0 | 0 | — |
case-17 | pass→pass | 11,961 | 10,076 | -16% | 1 | 1 | 0% | 2,408 | 4,554 | +89% | 0 | 0 | — |
case-18 | pass→pass | 16,137 | 13,156 | -18% | 1 | 1 | 0% | 2,777 | 5,367 | +93% | 0 | 0 | — |
case-19 | pass→pass | 9,743 | 5,447 | -44% | 1 | 1 | 0% | 1,812 | 3,983 | +120% | 0 | 0 | — |
case-20 | pass→pass | 13,757 | 13,779 | +0% | 1 | 1 | 0% | 2,394 | 5,857 | +145% | 0 | 0 | — |
case-21 | pass→pass | 6,598 | 5,592 | -15% | 1 | 1 | 0% | 1,324 | 3,900 | +195% | 0 | 0 | — |
case-22 | pass→pass | 21,722 | 22,299 | +3% | 1 | 1 | 0% | 3,233 | 6,480 | +100% | 0 | 0 | — |
case-23 | pass→pass | 13,130 | 14,049 | +7% | 1 | 1 | 0% | 2,424 | 5,307 | +119% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +4 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.