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.

Hardcoded or repetitive test data is one of the most common causes of misleading load test results. When every virtual user sends the same username, email address, or product ID, caches warm up unrealistically, database indexes only cover a tiny key space, and the load test ends up measuring a scenario that can never happen in production. This guide explains how to generate dynamic, realistic, and diverse test data — from Faker-style synthetic values to securely retrieved secrets — so your simulations reflect the true variety of production traffic.

Why Synthetic Data Matters

Avoid Caching Artifacts

Unique values per virtual user prevent in-memory and CDN caches from serving every request from cache, revealing true back-end performance.

Cover Edge Cases

Randomised names, emails, and numbers naturally exercise code paths that static data never reaches.

No Sensitive Data in Repos

Generated data means real PII and credentials stay out of your version control system and CI logs.

Generating Data with DataFaker

DataFaker is a Java library that generates realistic fake data: names, addresses, emails, phone numbers, credit card numbers, and hundreds of other categories.

Add the Dependency

<dependency>
  <groupId>net.datafaker</groupId>
  <artifactId>datafaker</artifactId>
  <version>2.3.1</version>
</dependency>

Building a Custom Feeder

The pattern is always the same: create a Faker instance, then wrap Stream.generate in an iterator() call so Gatling gets an infinite, lazy source of fresh records.
1

Create the Faker instance

import net.datafaker.Faker;
Faker faker = new Faker();
2

Generate the data inside the supplier

String firstName = faker.name().firstName();
String lastName  = faker.name().lastName();
3

Build the iterator Gatling will consume

import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Stream;

Iterator<Map<String, Object>> feeder =
    Stream.generate((Supplier<Map<String, Object>>) () -> {
      String first = faker.name().firstName();
      String last  = faker.name().lastName();
      return Map.of(
          "firstname", first,
          "lastname",  last
      );
    }).iterator();
4

Use the feeder in your scenario

ScenarioBuilder hello = scenario("Hello User")
  .exec(
    feed(feeder),
    http("Hello Endpoint")
      .post("/hello")
      .body(StringBody(
        "{\"firstname\": \"#{firstname}\", \"lastname\": \"#{lastname}\"}"
      )).asJson()
      .check(
        status().is(201),
        jsonPath("$.message")
          .is(session ->
            "Hello " + session.getString("firstname")
                     + " " + session.getString("lastname"))
      )
  );

Complete Simulation Example

package com.example;

import io.gatling.javaapi.core.*;
import io.gatling.javaapi.http.*;
import net.datafaker.Faker;

import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;

public class DataFakerSimulation extends Simulation {

  private final Faker faker = new Faker();

  private final Iterator<Map<String, Object>> feeder =
      Stream.generate((Supplier<Map<String, Object>>) () ->
          Map.of(
            "firstname", faker.name().firstName(),
            "lastname",  faker.name().lastName()
          )
      ).iterator();

  private final HttpProtocolBuilder httpProtocol =
      http.baseUrl("http://127.0.0.1:5000")
          .acceptHeader("application/json");

  private final ScenarioBuilder scn = scenario("Hello User")
      .exec(
        feed(feeder),
        http("Hello")
          .post("/hello")
          .body(StringBody(
            "{\"firstname\": \"#{firstname}\", \"lastname\": \"#{lastname}\"}"
          )).asJson()
          .check(status().is(201))
      );

  {
    setUp(scn.injectOpen(atOnceUsers(10)))
      .protocols(httpProtocol);
  }
}

Common DataFaker Providers

CategoryMethodExample Output
Namesfaker.name().firstName()"Ava"
Emailfaker.internet().emailAddress()"ava.jones@example.com"
Addressfaker.address().city()"Austin"
Phonefaker.phoneNumber().phoneNumber()"+1-555-123-4567"
UUIDfaker.internet().uuid()"550e8400-e29b-41d4..."
Numberfaker.number().numberBetween(1, 100)42
Datefaker.date().birthday()Date object

Generating UUIDs and Random Identifiers

For scenarios that require unique transaction IDs, correlation tokens, or idempotency keys, Java’s built-in UUID.randomUUID() is the simplest option — no extra dependency required.
Iterator<Map<String, Object>> idFeeder =
    Stream.generate((Supplier<Map<String, Object>>) () ->
        Map.of("correlationId", java.util.UUID.randomUUID().toString())
    ).iterator();

Generating CSV Data Programmatically

When you want a reproducible, static data file rather than runtime-generated values — useful for keeping test runs deterministic — generate the CSV file once before the simulation.
import java.io.*;
import java.nio.file.*;
import net.datafaker.Faker;

public class CsvGenerator {
  public static void main(String[] args) throws IOException {
    Faker faker = new Faker();
    Path output = Paths.get("src/test/resources/data/users.csv");

    try (BufferedWriter writer = Files.newBufferedWriter(output)) {
      writer.write("username,email,password\n");
      for (int i = 0; i < 10_000; i++) {
        writer.write(
          "user" + i + "," +
          faker.internet().emailAddress() + "," +
          faker.internet().password() + "\n"
        );
      }
    }
    System.out.println("Generated " + output.toAbsolutePath());
  }
}
Then use it as a standard feeder:
FeederBuilder<String> usersFeeder = csv("data/users.csv").circular();

AWS Secrets Manager for Secure Credentials

When your simulation needs real credentials — API keys, auth tokens, database passwords — retrieve them from AWS Secrets Manager at simulation startup rather than embedding them in files or environment variables that might leak into logs.
This approach requires Gatling Enterprise Edition with private locations and the AWS SDK for Java 2.x. The secret is fetched once per load generator, not once per virtual user.

IAM Policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/api-key"
    }
  ]
}

Fetching the Secret

import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;

public class SecureSimulation extends Simulation {

  private static final String API_KEY = loadSecret("prod/api-key");

  private static String loadSecret(String name) {
    try (SecretsManagerClient client = SecretsManagerClient.create()) {
      return client.getSecretValue(
        GetSecretValueRequest.builder().secretId(name).build()
      ).secretString();
    }
  }

  ScenarioBuilder scn = scenario("Secure API")
    .exec(http("Protected Request")
      .get("/api/data")
      .header("X-Api-Key", API_KEY)
      .check(status().is(200)));

  {
    setUp(scn.injectOpen(atOnceUsers(50)))
      .protocols(httpProtocol);
  }
}

Choosing the Right Approach

Data typeRecommended approach
User names, emails, addressesDataFaker custom iterator
Unique IDs, correlation tokensUUID.randomUUID() inline
Large static datasetsPre-generated CSV, stored in S3
Credentials and secretsAWS Secrets Manager
Small fixed datasetsCSV/JSON feeder file in resources/data/

Build docs developers (and LLMs) love