Gatling: Simulations, Injection & Checks
Gatling is a load/performance testing tool built on Scala with an asynchronous, non-blocking (Akka/Netty) architecture -- it can simulate thousands of concurrent virtual users from a single machine using far fewer OS threads than a naive thread-per-user design would need.
A Basic Simulation
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class CheckoutSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://api.example.com")
.acceptHeader("application/json")
// Feeder: real traffic isn't every user searching the same product --
// pull varied data per virtual user instead of hardcoding one value
val productFeeder = csv("products.csv").random
val scn = scenario("Browse and Checkout")
.feed(productFeeder)
.exec(
http("Get Homepage")
.get("/")
.check(status.is(200))
)
.pause(2, 5) // "think time" -- realistic delay, not back-to-back requests
.exec(
http("Search Product")
.get("/search?q=${productName}")
.check(status.is(200), jsonPath("$.results[0].id").saveAs("productId"))
)
.pause(1, 3)
.exec(
http("Add to Cart")
.post("/cart")
.body(StringBody("""{"productId": "${productId}"}"""))
.check(status.is(201))
)
// Injection profile: gradually ramp 1000 users over 60s, simulating
// organic traffic growth rather than an instant spike
setUp(
scn.inject(rampUsers(1000).during(60.seconds))
).protocols(httpProtocol)
}Injection Profiles
// Different injection shapes simulate different real-world patterns
atOnceUsers(500) // instant spike (flash sale)
rampUsers(1000).during(60.seconds) // gradual ramp (marketing campaign)
constantUsersPerSec(50).during(5.minutes) // sustained steady traffic
rampUsersPerSec(10).to(100).during(2.minutes) // increasing rate
// Distinct performance-testing goals, different injection profiles:
// Load testing -- expected/realistic traffic
// Stress testing -- well beyond capacity, to find the breaking point
// Soak testing -- sustained moderate load over hours, to catch leaksGrouping & the Recorder
// Group a multi-step business flow so the report aggregates it as
// a whole, not just per individual request
val scn = scenario("Checkout Flow")
.group("Checkout") {
exec(http("Browse").get("/products"))
.exec(http("Add to Cart").post("/cart"))
.exec(http("Pay").post("/checkout"))
}
// The Recorder captures real browser/proxy traffic and generates a
// starter simulation from it -- a working baseline to edit, not a
// locked, unmodifiable output
// $ ./bin/recorder.shKeep your own version of these notes — editable, searchable, and organised by your stack.
Start free