Gatling
01 / 02

Simulations, Injection & Checks

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 leaks

Grouping & 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.sh

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free