The most surprising thing about running Gatling across multiple injectors is that it’s not about distributing load, but about aggregating results.
Let’s see Gatling in action, but first, a quick setup. Imagine you have three machines that will act as your "injectors" (or "slaves"). Each machine needs Gatling installed, and importantly, they all need to be able to reach a central "master" or "controller" machine. On the master, you’ll be running the Gatling recorder or the Gatling Enterprise UI, and this is where all the final metrics will be compiled.
Here’s a simplified gatling.conf snippet you might see on an injector:
gatling {
core {
directory {
resources = "../user-files"
reportsOnly = ../results
}
}
http {
ssl {
useOpenSsl = true
}
}
charting {
max-plots = 100
}
remote {
controllers = ["192.168.1.100:8080"] # This is the IP and port of your master
}
}
And on the master, the relevant part of gatling.conf would look like this:
gatling {
core {
directory {
reportsOnly = ../results
}
}
remote {
akka {
# The port Akka remoting will listen on for injector connections
port = 8080
# The IP address to bind to. 0.0.0.0 means all network interfaces.
bindAddress = "0.0.0.0"
}
}
}
When you kick off a distributed test, you typically start the Gatling recorder on the master first. Then, you SSH into each injector machine and start Gatling without a specific simulation class. Gatling on the injector will see the remote.controllers configuration, connect to the master, and wait for instructions. The master, upon receiving a test command (often via the Gatling Enterprise UI or a command-line invocation that signals the master), will then tell all connected injectors to start running the specified simulation.
Each injector will run its portion of the load independently, generating its own set of raw results files (e.g., simulation_timestamp.log and simulation_timestamp.shakeless). However, it doesn’t send these raw logs to the master. Instead, the master, once all injectors have reported completion, initiates a results aggregation. It asks each injector to send its aggregated metrics. These aggregated metrics are far smaller than the raw logs and represent things like the total number of requests, average response times, and error counts from that specific injector. The master then combines these aggregated metrics from all injectors into a single, comprehensive set of reports.
This aggregation is crucial: you’re not seeing a merged stream of raw logs; you’re seeing Gatling’s internal aggregation logic applied per injector, and then those per-injector summaries are summed up on the master. This is why you often see a "waiting for remote nodes to finish" message, followed by a "aggregating results" phase. The "running simulation" phase happens concurrently on all injectors, but the "reporting" phase is a sequential, master-driven process.
The key levers you control are the network connectivity between injectors and the master, and ensuring the remote.controllers address on the injectors correctly points to the master’s Akka remoting port. The number of users you define in your simulation is then divided (or rather, each injector is instructed to run a portion of the total load, usually scaled by the number of injectors) so that the sum of users across all injectors reaches your target. For example, if you want to simulate 1000 users and have 5 injectors, each injector might be asked to run 200 users concurrently.
The one thing most people don’t realize is that the "simulation" running on the injector is still a complete, independent execution of your code. If your simulation has a bug that only manifests under specific conditions, you might see that bug on one injector but not another, and the aggregated results might mask this individual failure unless you specifically look for per-injector error rates (which Gatling Enterprise often surfaces).
The next step is understanding how to configure and manage the network ports for Akka remoting, especially in more complex network environments with firewalls.