Using Gatling CSV Feeders to Drive Realistic Load Tests
Learn how to load dynamic data from a CSV file into Gatling simulations, choose the right feeder strategy, and verify the behavior without risking memory overload.
25 Nov 2025, 17:16 UTC

Problem: Hard‑coded values make load tests unrealistic
When you record a scenario, Gatling often captures static usernames, product IDs, or tokens. Re‑playing the same values across thousands of virtual users hides issues like cache contention, rate‑limiting, or data‑dependent errors. To surface those problems you need each virtual user to see a different, yet repeatable, piece of data.
Thesis: Gatling’s feeder API lets you externalize test data and inject it safely into requests
By loading a CSV (or JSON, JDBC) into memory and binding its columns to session attributes, you can reference those attributes with Gatling’s EL syntax (${}) in headers, bodies, or query strings. The feeder also controls how data is consumed—circular, random, shuffle, or queue—so you can model the exact user behavior you want to simulate.
Setting up a CSV feeder
- Place the CSV under
src/test/resources/feeders. For example,users.csvwith columnsidandemail:
id,email
1,[contact removed]
2,[contact removed]
3,[contact removed]
2. In your Scala simulation, create a feeder and attach it before the request that needs the data:
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class UserSearchSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://api.example.com")
.acceptHeader("application/json")
// CSV feeder: circular repeats the file forever
val csvFeeder = csv("users.csv").circular
val scn = scenario("Search users")
.feed(csvFeeder) // injects id & email into the session
.exec(http("GET /search")
.get("/search")
.queryParam("userId", "${id}")
.queryParam("email", "${email}")
.check(status.is(200)))
.pause(1.second)
setUp(scn.inject(atOnceUsers(10)))
.protocols(httpProtocol)
}
3. Run the test with the Maven plugin (or Gradle) – no special permissions are needed beyond the ability to execute the build:
mvn gatling:test -Dgatling.simulationClass=UserSearchSimulation
Check the console output or the generated HTML report; each request should show the id and email values taken from the CSV in the order defined by the feeder strategy.
Choosing a feeder strategy
- circular – repeats the file indefinitely; useful when you want a predictable pattern that loops.
- random – picks a row uniformly at each invocation; good for simulating unpredictable user choices.
- shuffle – shuffles once then iterates; gives you a random order without replacement until the file is exhausted.
- queue – consumes each row exactly once; ideal for one‑time data loads (e.g., unique coupon codes).
The strategy you select directly influences the load pattern. For example, a queue feeder will cause the simulation to stop feeding new data after the CSV is exhausted, which may lead to fewer active users if you don’t restart the feeder.
Limitations and practical verification
Memory usage: The entire CSV is loaded into JVM memory. A 100 MB file with many columns can push heap usage close to the default -Xmx1g limit, risking OutOfMemoryError. Mitigation approaches:
- Split large files into smaller chunks and rotate feeders between simulations.
- Switch to a JDBC feeder when the data source is a database; it streams rows on demand.
- Monitor heap with
-XX:+PrintGCDetailsor a profiling tool while running a test with a deliberately oversized CSV to confirm the behavior.
Thread‑safety across runs: A feeder instance holds internal state (the position in the data). Re‑using the same feeder between separate setUp blocks without recreating it can cause unexpected reuse or exhaustion. Always define the feeder inside the simulation class or recreate it before each run.
To verify that the feeder works as expected:
- Add a simple logger step:
.exec(session => { println(session("id").as[String]); session })and confirm the printed values follow the chosen strategy. - Inspect the request details in the Gatling report; the query string should reflect the substituted EL expressions.
- Run the test with a small CSV (e.g., 5 rows) and a high user count; observe whether the feeder loops (circular) or stops (queue) as intended.
Actionable closing
Start by moving any static parameter that varies per user into a CSV feeder. Choose circular for steady‑state load, random for unbiased distribution, shuffle for a one‑off random order, and queue when each record must be used exactly once. Keep an eye on heap size when the feeder file grows, and consider a JDBC feeder or partitioned CSVs for very large datasets. With these steps your load tests will reflect real‑world variability without adding custom code.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.