skip to content

What do the gatling.charting.indicators.lowerBound and higherBound settings change in a Gatling HTML report, and when are they applied?

level: middleimportance: should knowfreq 38%

answer

  1. Two cut points, three time bands
  2. Defaults are 800 ms and 1200 ms
  3. A fourth bar counts failed requests
  4. Applied at report generation, not run time

basics

~10 s

They are the two cut points of the Response Time Ranges panel, defaulting to 800 ms and 1200 ms. Gatling applies them when the report is generated from simulation.log, not while the run executes.

solid answer

~40 s

`gatling.charting.indicators.lowerBound` and `higherBound` define the three time bands of the **Response Time Ranges** panel and of the equivalent block in the end-of-run console summary. With the defaults of 800 and 1200 the bands are `t < 800 ms`, `800 ms <= t < 1200 ms` and `t >= 1200 ms`, plus a fourth bar for failures — and status is tested first, so a failed request is counted as failed regardless of how fast it was. The bounds are run-wide: every ranges panel in the report, global and per request, uses the same two numbers. Crucially they are read when the **report is generated**, so changing them and regenerating with `-ro` redraws the same run's bars without re-running anything.

code

hocon · 4 lines
hocon
gatling.charting.indicators {
  lowerBound = 300
  higherBound = 1000
}

go deeper

for a junior

Be ready to say what the Response Time Ranges bars mean and where their 800 ms and 1200 ms defaults come from.

for a middle

Be ready to state the exact cascade: failures first, then strictly below the lower bound, then at or above the higher bound, then the middle band.

for a senior

Be ready to point out that the bounds are applied at report-generation time, so an old run can be re-cut with -ro and no re-execution.

for a principal

Be ready to argue where the charting configuration should live so that every report of a suite is drawn with the same bands, and to say when one pair of bounds stops being useful.

## What the two settings actually do `gatling.charting.indicators.lowerBound` and `gatling.charting.indicators.higherBound` live in `gatling.conf` (or are inherited from `gatling-defaults.conf`, where they are **800** and **1200**, both in milliseconds). They do exactly one job: they cut the response-time axis into bands for the **Response Time Ranges** panel. That panel appears three times over in a report — on `index.html` for the whole run, on each request's detail page for that request, and on each group's page, where it is titled *Group Duration Ranges* and is fed the group's wall-clock duration. Four bars, and the classification is a simple cascade: 1. Is the record a failure? If so it is counted as **failed** and nothing else is looked at. 2. Otherwise, is its time **strictly below** `lowerBound`? That is the fast band. 3. Otherwise, is its time **at or above** `higherBound`? That is the slow band. 4. Otherwise it falls in the middle band. The middle band is therefore the half-open interval `[lowerBound, higherBound)`: a request that took exactly 1200 ms with the defaults counts as slow, not middling. The end-of-run console summary prints the same four counts with literal labels — `OK: t < 800 ms`, `OK: 800 ms <= t < 1200 ms`, `OK: t >= 1200 ms` and `KO` — which is the clearest statement of the semantics Gatling itself gives you. ## When they are applied, and why that matters Nothing about these bounds is baked into the run. `simulation.log` records raw per-request timings; the bucketing happens when the HTML report is generated, from whichever configuration is resolved at that moment. Three consequences follow: - **You can re-cut an old run.** Change the bounds, run with `--reports-only` (`-ro <directoryName>`) against the existing results folder, and you get new bars over the same data. Nothing is re-executed. - **Two people can produce two different reports from one run** if their `gatling.conf` differs, which is a reason to keep the file with the simulations rather than on a machine. - **They cost nothing at run time.** Tightening them does not slow the load generator or change what it sends. ## What they do not touch This is where the question is usually decided. The bounds are presentation, and their reach is narrow: | surface | affected by the bounds? | |---|---| | Response Time Ranges panel (and its console equivalent) | **yes** — this is their only job | | Stats table response-time columns | no — those are min, the four configured percentiles, max, mean and standard deviation | | Response Time Percentiles over Time chart | no — it plots a fixed ladder of ranks | | Response Time Distribution histogram | no — its buckets come from the data, not the bounds | | Assertions, and therefore the run's exit code | no — the bounds make nothing pass or fail | That last row is the one candidates get wrong. A report in which every bar sits in the slow band is not a failed run; Gatling's only automatic verdict comes from assertions, and the bounds are invisible to them. Choosing the response-time target a run should be judged against is a performance-testing question that lives outside Gatling; choosing where the report draws its bars is this setting. ## Practical shape The useful setting for the pair is *whatever your service's own expectation is*, one number a little under it and one a little over, so the three bands read as "comfortable", "borderline" and "bad". Left at 800 and 1200 they are arbitrary for most services: they came out of `gatling-defaults.conf`, not out of your requirements, and a panel showing everything in the fast band tells you only that your service is quicker than a number nobody chose. Because the values are run-wide, a suite that mixes a 100 ms lookup with a 3-second report export cannot make both read well on one panel. For those, the per-request detail pages and their own stats tables are the surfaces to argue from, and the ranges panel on `index.html` drops back to being a coarse overview — useful for the shape of a run, not for a per-endpoint claim. One last habit worth forming: because the bands are recomputed on every generation, treat a stored report as a picture taken with particular settings rather than as the run itself. If you keep reports as release artifacts, keep the configuration that drew them in the same repository, or a report from six months ago cannot be compared with one from today even though both describe real runs.

  • Can different requests use different bounds?
    No. `lowerBound` and `higherBound` are run-wide: they are read once from the resolved configuration and the same two cut points draw every Response Time Ranges panel in the report, global, per request and per group. If your requests have genuinely different expectations, the per-request detail pages and their own statistics are the place to look, not this panel.
  • Do the bounds change the Stats table at all?
    No. The Stats table's response-time half is min, the four configured percentiles, max, mean and standard deviation — none of them bucketed. The bounds touch only the ranges panel and the matching block of the end-of-run console summary.

saying these in an interview costs you the question

  • Thinks the bounds make a run pass or fail
  • Assumes a failed fast request counts in the fastest band
  • Believes the bounds are recorded into simulation.log at run time
  • Expects the bounds to be settable per request