Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/gatling/gatling.io-doc/llms.txt

Use this file to discover all available pages before exploring further.

An injection profile defines when and how fast virtual users are introduced into a scenario. Gatling supports two fundamentally different models: the open model, where you control the arrival rate of users, and the closed model, where you control the number of concurrent users at any given moment. Choosing the correct model is critical for producing meaningful results — see Workload Models for a deeper explanation. The injection profile is defined by calling injectOpen or injectClosed (just inject in Scala) on a ScenarioBuilder, then passing one or more injection steps that are processed sequentially.

Open Model

In the open model, you specify how many users arrive per unit of time. Use injectOpen to configure open injection.

Core Building Blocks

setUp(
  scn.injectOpen(
    nothingFor(4),                                  // 1. pause for 4 seconds
    atOnceUsers(10),                                // 2. inject 10 users at once
    rampUsers(10).during(5),                        // 3. ramp 10 users over 5 seconds
    constantUsersPerSec(20).during(15),             // 4. 20 users/sec for 15 seconds (regular)
    constantUsersPerSec(20).during(15).randomized(),// 5. 20 users/sec for 15 seconds (randomized)
    rampUsersPerSec(10).to(20).during(10),          // 6. ramp from 10 to 20 users/sec over 10 seconds
    rampUsersPerSec(10).to(20).during(10).randomized(), // 7. same but with randomized intervals
    stressPeakUsers(1000).during(20)                // 8. heaviside step to inject 1000 users over 20s
  ).protocols(httpProtocol)
);

nothingFor(duration)

Pause for the specified duration before the next step begins.

atOnceUsers(n)

Inject all n users simultaneously at the start of this step.

rampUsers(n).during(duration)

Inject n users evenly spread over a time window.

constantUsersPerSec(rate).during(duration)

Inject at a constant rate (users/sec) for the given duration. Add .randomized() for randomized intervals.

rampUsersPerSec(r1).to(r2).during(duration)

Linearly increase the arrival rate from r1 to r2 over the duration. Add .randomized() for randomized intervals.

stressPeakUsers(n).during(duration)

Inject n users following a Heaviside step function approximation — a smooth S-curve spike.
Rates can be fractional values, e.g. constantUsersPerSec(0.5).during(60) injects one user every 2 seconds.

Capacity Stairs (incrementUsersPerSec)

For capacity tests where you progressively increase load in discrete steps, Gatling provides the incrementUsersPerSec helper:
setUp(
  // levels of 10, 15, 20, 25, 30 users/sec
  // each level lasts 10 seconds, separated by 10-second ramps
  scn.injectOpen(
    incrementUsersPerSec(5.0)
      .times(5)
      .eachLevelLasting(10)
      .separatedByRampsLasting(10)
      .startingFrom(10) // Double
  )
);
separatedByRampsLasting and startingFrom are both optional. Without a ramp the test jumps directly between levels; without startingFrom it begins at 0 users/sec.

Closed Model

In the closed model, you specify how many users are concurrently active in the system at any moment. Use injectClosed to configure closed injection.

Core Building Blocks

setUp(
  scn.injectClosed(
    constantConcurrentUsers(10).during(10),    // 1. hold 10 concurrent users for 10 seconds
    rampConcurrentUsers(10).to(20).during(10)  // 2. ramp from 10 to 20 concurrent users over 10s
  )
);
Ramping down the number of concurrent users does not forcefully interrupt running virtual users. Users terminate only when they complete their scenario. Plan your scenario length accordingly.

Capacity Stairs (incrementConcurrentUsers)

setUp(
  // levels of 10, 15, 20, 25, 30 concurrent users
  // each level lasts 10 seconds, separated by 10-second ramps
  scn.injectClosed(
    incrementConcurrentUsers(5)
      .times(5)
      .eachLevelLasting(10)
      .separatedByRampsLasting(10)
      .startingFrom(10) // Int
  )
);

Chaining Injection Steps

For a single scenario you can pass a sequence of injection steps. All steps must belong to the same model (open or closed). The next step begins once all virtual users from the current step have started.
// open model: ramp to 100 users/sec then hold steady
setUp(
  scn.injectOpen(
    rampUsersPerSec(0).to(100).during(Duration.ofMinutes(1)),
    constantUsersPerSec(100).during(Duration.ofMinutes(10))
  )
);

// closed model: ramp to 100 concurrent users then hold steady
setUp(
  scn.injectClosed(
    rampConcurrentUsers(0).to(100).during(Duration.ofMinutes(1)),
    constantConcurrentUsers(100).during(Duration.ofMinutes(10))
  )
);

Concurrent Scenarios

Multiple scenarios configured in the same setUp block start at the same time and run in parallel.
setUp(
  scenario1.injectOpen(injectionProfile1),
  scenario2.injectOpen(injectionProfile2)
);

Sequential Scenarios

Use andThen to chain scenarios so that child scenarios start only after all users from the parent scenario have completed.
setUp(
  parent.injectClosed(injectionProfile)
    // child1 and child2 start together when the last parent user finishes
    .andThen(
      child1.injectClosed(injectionProfile)
        // grandChild starts when the last child1 user finishes
        .andThen(grandChild.injectClosed(injectionProfile)),
      child2.injectClosed(injectionProfile)
    ).andThen(
      // child3 starts when the last grandChild and child2 users finish
      child3.injectClosed(injectionProfile)
    )
);
Sequential scenarios are the recommended approach when you need to perform Gatling SDK actions (e.g., fetching an auth token) before the main load begins — something that cannot be done in lifecycle hooks.

Disabling Load Sharding (Enterprise Edition)

By default, Gatling Enterprise Edition distributes your injection profile evenly across all load generator nodes. Use noShard to disable this — all nodes will run the full injection and throttle profiles as defined. This is typically used when a pre-scenario (e.g., token retrieval) should run on every node rather than just one.
setUp(
  // parent load is NOT sharded — runs on every node
  parent.injectOpen(atOnceUsers(1)).noShard()
    .andThen(
      // child load IS sharded across nodes
      child1.injectClosed(injectionProfile)
    )
);

Build docs developers (and LLMs) love