Skip to content

05 — Feeders

A feeder is a data source that injects values into each virtual user's session. Use feeders to parameterise requests with unique usernames, product IDs, search terms, etc.


Feeding strategies

Strategy Method Behaviour
Queue .queue() Each record consumed once; fails if exhausted
Random .random() Pick random record each time
Shuffle .shuffle() Shuffle then consume in order
Circular .circular() Round-robin, wraps around

Default (no method call) is queue.

// Java
csv("users.csv").circular()

// Kotlin
csv("users.csv").circular()

CSV feeder

File: src/test/resources/data/users.csv

username,password,role
alice,s3cr3t,user
bob,p@ssw0rd,admin
carol,abc123,user
// Java
FeederBuilder<String> feeder = csv("data/users.csv").circular();

ScenarioBuilder scn = scenario("Login")
    .feed(feeder)
    .exec(http("Login")
        .post("/login")
        .formParam("username", "#{username}")
        .formParam("password", "#{password}")
        .check(status().is(200)));
// Kotlin
val feeder = csv("data/users.csv").circular()

val scn = scenario("Login")
    .feed(feeder)
    .exec(
        http("Login").post("/login")
            .formParam("username", "#{username}")
            .formParam("password", "#{password}")
            .check(status().`is`(200))
    )

Tab-separated values

tsv("data/products.tsv").random()

Separator override

separatedValues("data/custom.csv", ';').circular()

JSON feeder

File: src/test/resources/data/products.json

[
  {"id": 1, "name": "Widget", "price": 9.99},
  {"id": 2, "name": "Gadget", "price": 24.99},
  {"id": 3, "name": "Doohickey", "price": 4.49}
]
// Java
FeederBuilder<Object> feeder = jsonFile("data/products.json").random();

scenario("Browse product")
    .feed(feeder)
    .exec(http("Product").get("/products/#{id}"))
// Kotlin
val feeder = jsonFile("data/products.json").random()

Programmatic feeder

Create an Iterator<Map<String, Object>> from any source.

Java — infinite random data

import java.util.Map;
import java.util.Random;
import java.util.Iterator;

Random rng = new Random();

Iterator<Map<String, Object>> feeder = Stream.generate(() ->
    Map.<String, Object>of(
        "userId", rng.nextInt(100_000),
        "amount", rng.nextDouble() * 1000
    )
).iterator();

scenario("Random payments")
    .feed(feeder)
    .exec(http("Pay").post("/payments")
        .body(StringBody("""{"userId":#{userId},"amount":#{amount}}"""))
        .asJson())

Kotlin — infinite random data

import java.util.Random

val rng = Random()

val feeder = generateSequence {
    mapOf(
        "userId" to rng.nextInt(100_000),
        "amount" to rng.nextDouble() * 1000
    )
}.iterator()

val scn = scenario("Random payments")
    .feed(feeder)
    .exec(
        http("Pay").post("/payments")
            .body(StringBody("""{"userId":#{userId},"amount":#{amount}}"""))
            .asJson()
    )

Record per iteration vs record per user

By default feed() advances the feeder once per user per call. To advance multiple records at once:

.feed(feeder, 5)   // inject 5 records: #{username1}, #{username2}, …

Feeding at a specific point

You can call .feed() anywhere in the chain — it doesn't have to be first:

scenario("Scenario")
    .exec(http("Home").get("/"))
    .feed(productFeeder)                // load product data here
    .exec(http("Product").get("/products/#{id}"))

Unzipping feeders (joining two feeders)

FeederBuilder<String> users = csv("users.csv").circular();
FeederBuilder<String> products = csv("products.csv").random();

scenario("Browse as user")
    .feed(users)
    .feed(products)
    .exec(http("View product as user")
        .get("/users/#{username}/products/#{id}"))

Feeder sharing

Feeders are shared across all virtual users by default — all users consume records from the same feeder instance. The feeding strategy controls how records are selected:

  • .queue() (default) — each record is consumed exactly once, in order. Once exhausted, an error is thrown.
  • .circular() — wraps around when all records have been consumed.
  • .random() — picks a random record each time.
  • .shuffle() — shuffles the records, then consumes them in order like queue.
// Each record consumed exactly once across all virtual users
csv("data/unique-tokens.csv").queue()

Use .queue() when each data row should be consumed exactly once (e.g. unique invite codes).