Using Gatling Feeders and Checks to Avoid Skewed Load‑Test Results
Learn how to feed each virtual user unique data from a CSV and validate responses with Gatling checks so your load test reflects real‑world behavior.
20 Aug 2026, 06:43 UTC

The problem: shared data hides real performance
When a load test reuses the same login credentials or search term for every virtual user, caches and per‑account state in the application can make responses appear faster than they would be in production. The result is an optimistic picture that can miss bottlenecks that only appear under varied, realistic workloads.
Thesis: feeders + checks give you per‑user realism and validation
Gatling’s feeder mechanism supplies each virtual user a distinct record from a CSV, JSON, JDBC, or Redis source as the test reaches the feed step. Checks turn raw HTTP assertions into business‑logic validation, allowing you to fail a test when a 200 response actually carries an error payload. Together they let you shape realistic traffic and assert correctness in the same simulation.
How feeders work
A feeder is an iterator of maps. In a scenario you call feed(csv("users.csv")); each time a virtual user passes that step, Gatling pops the next record and injects its columns into the user’s session. You later reference them with EL syntax, e.g. ${username}. The default strategy is queue: records are consumed sequentially and the test fails when the feeder runs out. Other strategies (random, shuffle, circular) control what happens after exhaustion.
Turning checks into session data
The simplest check validates the HTTP status: status.is(200). You can chain additional checks that extract values from the response and store them for later requests:
jsonPath("$.token").saveAs("authToken")
Saved values live in the session, so a subsequent request can use ${authToken} as a header or query parameter. If the extraction fails, the check marks the request as failed, catching cases where a 200 OK masks an error payload.
Worked example: login‑then‑get‑account flow
The following Scala DSL snippet shows a complete simulation that:
- Loads credentials from
credentials.csv(columns:username,password). - Posts a login request, asserts status 200, and saves the returned
accountId. - GETs the account endpoint using the saved
accountId. - Uses a ramp‑up injection of 100 users over 2 minutes.
- Adds a global SLO assertion on the 95th‑percentile response time.
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class AccountSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://api.example.com")
.acceptHeader("application/json")
val credentialsFeeder = csv("credentials.csv").queue
val scn = scenario("Login and fetch account")
.feed(credentialsFeeder)
.exec(
http("Login")
.post("/login")
.body(StringBody("""{
"username": "${username}",
"password": "${password}"
}""")).asJson
.check(status.is(200))
.check(jsonPath("$.accountId").saveAs("accountId"))
)
.exec(
http("Get Account")
.get("/accounts/${accountId}")
.check(status.is(200))
)
setUp(
scn.inject(rampUsers(100).during(2.minutes))
).protocols(httpProtocol)
.assertions(global.responseTime.percentile95.lt(800))
}
Place the CSV file credentials.csv in the src/test/resources folder (or wherever your build expects resources). Each line should look like:
username,password alice,secret1 bob,secret2 ...
Trade‑offs and limitations
- Feeder memory: CSV feeders are read entirely into the driver JVM. Very large files (millions of rows) can exhaust heap; consider splitting the file or using a JDBC/Redis‑backed feeder.
- Queue exhaustion: With the default
queuestrategy the test will fail if virtual users exceed the number of rows. Switch tocircularorshuffleif you want reuse, or size your CSV to match the expected load. - Check overhead: Each check adds CPU work on the generator. At extremely high throughput the Gatling process itself can become the bottleneck before the system under test.
- DSL choice: Gatling now ships both Scala and Java DSLs. The example uses the stable Scala DSL; if you prefer Java, verify the equivalent methods (
feed,check) in the Java DSL documentation for your Gatling version.
Actionable closing: verify and gate your pipeline
To confirm the simulation works as described:
- Run the test with your build tool (e.g.,
./gatling.sh -s AccountSimulationor via the Maven/Gradle plugin). - Open the generated HTML report under
target/gatlingand inspect theLoginandGet Accountrequests; ensure theaccountIdcolumn appears in the session details. - Point the feeder at a file with fewer rows than the injected users and observe the failure; then change the feeder to
.circularand see the test continue. - Add a deliberately tight assertion, such as
global.responseTime.percentile95.lt(200), run the test in your CI pipeline, and verify the build fails—proving the quality gate works end‑to‑end.
By feeding each virtual user unique credentials and validating responses with checks, you move from a optimistic, cached‑friendly test to a realistic load scenario that can uncover true performance limits and be enforced as an automated gate in your delivery pipeline.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.