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.

The majority of modern applications are deployed as Docker containers, making container-aware load testing a fundamental part of any performance validation strategy. Load testing a Dockerized application is not fundamentally different from testing any other application — Gatling connects to the port exposed by the container just as it would to any HTTP endpoint — but the container context introduces important considerations around environment fidelity, monitoring, and CI/CD integration that this guide addresses in full.

Preparing for Load Testing a Docker Container

Before writing your first Gatling scenario, establish the same foundations you would for any load test:
1

Define objectives and success criteria

Agree on concrete thresholds — for example, p95 response time under 200 ms at 500 concurrent users — before starting. Vague objectives lead to inconclusive tests.
2

Build a representative environment

The container configuration, resource limits (--memory, --cpus), and network topology of your test environment should match production as closely as possible. Differences in CPU and memory allocations directly affect the results.
3

Enable container monitoring

Use Docker stats, cAdvisor, or an APM tool to track CPU usage, memory consumption, and network I/O on the container during the load test. This lets you distinguish application bottlenecks from container resource limits.
4

Prepare failure scenarios

Plan to test container crashes, network partitions, and resource exhaustion — not just the happy path. Gatling’s configurable injection profiles let you push beyond normal operating parameters deliberately.

Example: A TypeScript REST API in Docker

The Application

Here is a minimal Express/TypeScript API with two endpoints:
// server.ts
import express, { Request, Response } from 'express';

const app = express();
const port = 3000;

interface Game {
  title: string;
  type: string;
}

const games: Game[] = [
  { title: 'RL',        type: 'Sports' },
  { title: 'FIFA',      type: 'Sports' },
  { title: 'Fortnite',  type: 'Battle Royale' },
  { title: 'Minecraft', type: 'Sandbox' },
  { title: 'CS2',       type: 'Shooter' }
];

// Returns a random game
app.get('/games', (_, res: Response) => {
  const randomGame = games[Math.floor(Math.random() * games.length)];
  res.json({ game: randomGame.title });
});

// Returns details for a specific game by title
app.get('/game/:title', (req: Request, res: Response) => {
  const game = games.find(
    g => g.title.toLowerCase() === req.params.title.toLowerCase()
  );
  game
    ? res.json({ title: game.title, type: game.type })
    : res.status(404).json({ message: 'Game not found' });
});

app.listen(port, () => console.log(`Server running on http://localhost:${port}`));

The Dockerfile

FROM node:22

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install
RUN npm install -g typescript

COPY . .
RUN tsc

EXPOSE 3000

CMD ["node", "server.js"]

Build and Start the Container

# Build the image
docker build -t myapi .

# Run the container, exposing port 3000
docker run -p 3000:3000 myapi
You should see:
Server running on http://localhost:3000/

Writing the Gatling Simulation

The TypeScript Gatling simulation below models the user journey: first, fetch a random game name; then, use that game name to fetch its details.
// myapi.gatling.ts
import {
  simulation,
  scenario,
  exec,
  atOnceUsers,
  jsonPath,
} from "@gatling.io/core";
import { http } from "@gatling.io/http";

export default simulation((setUp) => {

  const httpProtocol = http
    .baseUrl("http://localhost:3000")
    .acceptHeader("application/json");

  // Step 1: Get a random game — save the name to the session
  const GetGame = exec(
    http("Get random game")
      .get("/games")
      .check(jsonPath("$.game").saveAs("GameName"))
  );

  // Step 2: Use the saved game name to fetch its details
  const GetType = exec(
    http("Get game type")
      .get("/game/#{GameName}")
      .check(status().in(200, 404)) // 404 is acceptable for unknown names
  );

  const GetGameAndType = scenario("Get Game and Type")
    .exec(GetGame, GetType);

  setUp(
    GetGameAndType.injectOpen(atOnceUsers(1))
  ).protocols(httpProtocol);
});
Run the simulation:
npx gatling run --typescript --simulation myapi

Scaling Up the Load Test

Once the single-user run confirms the scenario works end-to-end, increase the injection profile to stress-test the container:
setUp(
  GetGameAndType.injectOpen(
    rampUsers(500).during(60)  // Ramp to 500 concurrent users over 60 seconds
  )
).protocols(httpProtocol)
 .assertions(
   global().responseTime().percentile(95).lt(200),  // p95 < 200 ms
   global().successfulRequests().percent().gt(99.0) // > 99% success
 );

Best Practices for Docker Load Testing

Start load testing early

Integrate Docker load tests into your CI/CD pipeline from the first sprint. Finding container resource constraints late in development is far more expensive to fix than finding them early.

Match production resource limits

Always test with the same --memory and --cpus flags you use in production. A container allowed unlimited CPU in testing will produce artificially good results.

Test failover and recovery

Use docker stop mid-test to simulate container crashes and verify that your application restarts and recovers within an acceptable time frame.

Benchmark across releases

Gatling Enterprise Edition stores every run’s metrics, enabling you to compare container performance across Docker image versions and spot regressions introduced by dependency upgrades.

Running Distributed Tests with Gatling Enterprise Edition

For high-concurrency tests that a single load generator cannot produce alone, Gatling Enterprise Edition lets you deploy multiple distributed load generators across cloud regions with a single click. The same TypeScript simulation file you ran locally runs unchanged on the Enterprise platform — no refactoring required.
# Deploy the simulation to Gatling Enterprise Edition
export GATLING_ENTERPRISE_API_TOKEN=<your-token>
npx gatling enterprise-deploy
After deploying, create a simulation in the Gatling Enterprise UI, point it at your containerised application’s public or private endpoint, and launch a distributed load test with the load generators co-located closest to your container deployment region.

Build docs developers (and LLMs) love