skip to content

In a Gatling assertion, what does the `percentile3` response-time metric measure, and what can change its meaning without the simulation code changing?

level: middleimportance: should knowfreq 44%

answer

  1. The numbered four are configurable, not constants
  2. Defaults are 50, 75, 95 and 99
  3. Key lives under gatling.charting.indicators
  4. percentile(v) takes a percentage, 0 to 100
  5. Slot resolved when the assertion is built

basics

~20 s

It asserts on the third configured percentile, which defaults to the 95th but is read from gatling.charting.indicators.percentile3. Changing that key, or overriding it with a system property, silently repoints the same line of code at a different percentile.

solid answer

~40 s

`percentile1` through `percentile4` are not fixed percentiles. Each reads a key from `gatling.conf` - `gatling.charting.indicators.percentile1` to `percentile4` - defaulting to 50, 75, 95 and 99. They exist so that the figures you gate on are the same four the report's statistics table and the end-of-run console summary show. The slot is resolved when the assertion is built, so the registered assertion carries a literal number. That makes the meaning of `percentile3()` invisible from the simulation file, and a system property such as `-Dgatling.charting.indicators.percentile3=99` changes it for a whole run with no warning. `percentile(95.0)` takes the percentage directly, always means what it says, and is the only way to reach a percentile the report's statistics table does not list.

code

hocon · 10 lines
hocon
gatling {
  charting {
    indicators {
      percentile1 = 50
      percentile2 = 75
      percentile3 = 95
      percentile4 = 99
    }
  }
}

go deeper

for a junior

Be ready to say that the four numbered percentiles default to 50, 75, 95 and 99 and that percentile(value) lets you name any percentage directly.

for a middle

Be ready to name the configuration key behind the numbered slots and to explain that the slot is resolved when the assertion is constructed.

for a senior

Be ready to explain how a system property override changes a suite's pass rules for one run with no warning, and how you would prevent that.

for a principal

Be ready to decide whether reported percentiles and gate percentiles should move together, and to make that decision explicit rather than accidental.

## The four numbered slots are configuration, not constants Gatling's response-time metric link offers `percentile1`, `percentile2`, `percentile3` and `percentile4` alongside the explicit `percentile(value)`. The numbered four look like fixed percentiles and are almost always described as p50, p75, p95 and p99. They are not fixed. Each one reads a configuration key: | method | configuration key | default | |---|---|---| | `percentile1` | `gatling.charting.indicators.percentile1` | `50` | | `percentile2` | `gatling.charting.indicators.percentile2` | `75` | | `percentile3` | `gatling.charting.indicators.percentile3` | `95` | | `percentile4` | `gatling.charting.indicators.percentile4` | `99` | So `global().responseTime().percentile3().lt(500)` asserts that the **95th** percentile response time over all requests is under 500 ms *with the shipped defaults*. Change that one key in `gatling.conf` and the same unedited line of simulation code now asserts something else entirely. ## Why the slots exist at all These four keys were not invented for assertions. They are the four percentile columns of the HTML report's statistics table and of the console summary printed once the run is over, and the assertion methods reuse them so that the number you gate on is necessarily one of the numbers your report shows. That is a real benefit: a team that wants p90 and p99.9 in its statistics table gets assertions that can name those same figures without a second knob. The cost is the coupling. The percentile the assertion means lives in a different file from the assertion, and the key that moves it is filed under `charting` — a word that gives no hint that a pass rule depends on it. A reader of the simulation alone cannot tell what `percentile3()` means. ## How the resolution actually happens The slot is resolved **when the assertion object is built**, not when it is evaluated. `percentile3()` is defined as a call to `percentile(v)` with `v` read from the loaded configuration, so the assertion that ends up registered on `setUp` carries a literal percentile number in it. Gatling's own DSL test pins this: building `global.responseTime.percentile3.is(300)` under a test configuration produces an assertion whose target is the 95th percentile as a plain value. Two practical consequences follow: - The configuration that matters is the one loaded by the JVM running the simulation. `gatling.conf` is resolved from the **classpath**, and a system property overrides it, so `-Dgatling.charting.indicators.percentile3=99` on the command line silently changes what every `percentile3()` assertion in the suite means for that run. - Regenerating a report from an existing run does not re-resolve anything the assertion already fixed at build time; the percentile was chosen when the simulation was constructed. ## `percentile(value)` is the version that says what it means The explicit form takes the percentage directly, as a value between 0 and 100: ```java global().responseTime().percentile(95.0).lt(500); // always p95 global().responseTime().percentile(99.9).lt(3000); // p99.9, which no numbered slot reaches by default ``` Two things are worth noting about it. First, the argument is a **percentage**, so p99.9 is written `99.9` and not `0.999`; passing a fraction asks for a percentile below the first percent of the distribution. Second, `percentile(v)` is not limited to the four configured values, which is the only way to assert on a percentile your report's statistics table does not list. ## The same four keys drive what you can see Because the indicator keys also select the percentile columns of the generated HTML report's statistics table and of the console summary printed at the end of the run, the four slots tie three things together: - which percentiles the report lists in its **statistics table**; - which percentiles the final console summary prints after the run — and which therefore disappear entirely when report generation is switched off, since that summary is printed by the report generator; - which percentiles `percentile1` through `percentile4` assert on. Two things they do **not** reach are worth knowing, because both are commonly assumed. The "Response Time Percentiles over Time" chart plots a fixed ladder — min, p25, p50, p75, p80, p85, p90, p95, p99, max — computed without ever consulting the indicator keys, so retuning `percentile3` moves the statistics table and the assertion and leaves that chart exactly as it was. And the live console ticker printed while the simulation is running carries no percentiles at all: it shows elapsed time, the global and per-request OK/KO counters, errors and the per-scenario user-progression bar, and nothing else. That is useful when you want them aligned and awkward when you do not. A team that widens its reported percentiles to include p99.9 for diagnosis has, in the same edit, changed what a `percentile4()` assertion means for every simulation in the repository. Nothing about the change looks like a change to a pass rule, and code review of the simulation files will not surface it because no simulation file was touched. ## Which to use The choice is a genuine trade-off rather than a rule: 1. Use `percentile(95.0)` when the assertion must mean the same thing to anyone who reads the file, and in any suite where the configuration is not controlled by the same people who own the simulations. It is self-documenting and immune to a configuration change or a stray system property. 2. Use `percentile3()` when you deliberately want the gate and the report to move together — a team that re-tunes its reported percentiles and wants the pass rules to follow automatically. If you take the numbered form, state the resolved percentile in a comment beside it, and treat the four keys as part of the suite's public contract rather than as a display preference. The failure mode is quiet: nothing errors, nothing warns, and the run simply starts judging a different percentile than the one everybody believes is being judged.

  • What does `percentile(0.95)` assert in Gatling?
    The 0.95th percentile - essentially the fastest half-percent of responses - not the 95th. The argument is a percentage between 0 and 100, so p95 is written `95.0` and p99.9 is written `99.9`. Passing a fraction produces a rule that almost anything satisfies, which is why it fails silently rather than loudly.
  • If two teams share one gatling.conf, what is the risk of writing assertions with percentile4()?
    Either team can retune the reported percentiles and change every `percentile4()` assertion in the other team's suites at the same time, with no compile error and no warning. Treat the four indicator keys as a shared contract, or pin the percentile in the assertion with `percentile(v)` so the file says what it means.

saying these in an interview costs you the question

  • Believing percentile3 is hardcoded to the 95th percentile
  • Passing a fraction such as 0.95 to percentile(value)
  • Assuming the indicator keys only affect the report, not assertions
  • Expecting a warning when a system property moves a percentile