Parameterizing Gatling Load Tests with Feeders: A Practical Guide
Learn how Gatling feeders inject dynamic test data from CSV, JSON, JDBC, Redis or custom sources, with a concrete example, setup steps, and key limitations to watch.
15 Apr 2026, 04:09 UTC

Problem: Hard‑coded data makes realistic load tests brittle
When you simulate thousands of virtual users logging into an application, each user needs a unique credential set or a distinct product ID. Embedding those values directly in the script forces you to maintain large arrays or duplicate rows, and it prevents the test from reflecting real‑world variability.
Thesis: Gatling’s feeder mechanism injects external data lazily, giving each virtual user a unique row without blowing up memory
Feeders read from CSV, JSON, JDBC, Redis, or a custom Scala function and make the next record available to the scenario exactly when a virtual user reaches the feed step. Because the data is read on demand, the JVM only holds what is needed for the current iteration unless you explicitly choose a loader that caches the whole file.
Understanding feeder types and configuration
- CSV feeder:
val csvFeeder = csv(\"users.csv\").circular(or.random,.queue). - JSON feeder: works similarly with
jsonFile. - JDBC feeder: pulls rows from a database query.
- Redis feeder: reads from a Redis key/value store.
- Custom feeder: any
Iterator[Map[String, Any]]wrapped withfeeder.
The loader (circular, random, queue) determines how the feeder behaves when it reaches the end of the source.
Worked example: feeding login credentials from a CSV
- Create
src/test/resources/users.csvwith a header row:
id,name,password
1001,alice,Al!ce2023
1002,bob,Bo!b2023
1003,charlie,Ch@rlie2023
- Define the feeder and scenario in a Gatling simulation (Scala):
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class LoginSimulation extends Simulation {
val httpProtocol = http
.baseUrl(\"https://example.com\")
.acceptHeader(\"application/json\")
val csvFeeder = csv(\"users.csv\").circular
val scn = scenario(\"Login with feeder\")
.feed(csvFeeder)
.exec(http(\"POST /login\")
.post(\"/api/login\")
.body(StringBody(\"{\"username\":\"${name}\",\"password\":\"${password}\"}\"))
.asJson
.check(status.is(200)))
setUp(scn.inject(constantUsersPerSec(10) during (30.seconds)))
.protocols(httpProtocol)
}
- Run the simulation (e.g., via Maven):
mvn gatling:test -Dgatling.simulationClass=LoginSimulation - Observe the console: each virtual user prints the
id,name, andpasswordfrom the next CSV row. - Open the generated HTML report (
target/gatling/...) and inspect a request; the payload will show the dynamically injected values.
Trade‑offs and limitations
- Memory usage: Using
.circularor.randomon a large CSV forces Gatling to load the entire file into JVM memory. If the file exceeds available heap, you may seeOutOfMemoryError. Prefer.queueor split the file into smaller chunks when the dataset is big. - Feeder exhaustion: A
.queuefeeder that runs out of rows throws anIllegalStateExceptionand aborts the test. Mitigate by resetting the feeder (.queuewithshuffle) or by using a circular loader when repetition is acceptable. - Thread‑safety: Feeders are stateless by default, but custom feeders that rely on mutable collections need explicit synchronization if shared across simulations.
Actionable closing
Start small: create a CSV with a few rows, wire it into a scenario with feed, and verify the values appear in request payloads or console logs. Once the basic flow works, scale to your production‑size dataset, choosing the appropriate loader to balance realism and memory footprint. Feeders let you keep your test scripts clean while delivering the varied data real load testing demands.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.