Concepts

Coordinated omission: what it is and how to avoid it

7 min read

Coordinated omission is a measurement error in which a load generator waits for each slow response before sending its next request, so it sends fewer requests just when the system is slow and records too few of the bad moments. The percentiles you read afterwards then look better than what users lived through. You avoid it by sending requests on a schedule that ignores response times, and by timing each request from the moment it was due to be sent.

The tool facts below come from each project’s own documentation or repository, checked on 9 October 2026.

ToolWhat it offersWhat to check
wrk2A constant rate (-R), latency timed from the planned send--u_latency adds the uncorrected view
HdrHistogramTwo methods that back-fill missing samplesApply one of them, never both
k6Arrival-rate executorsThe dropped_iterations counter
GatlinginjectOpen steps such as constantUsersPerSecThe steps sit inside injectOpen
Locustconstant_throughput paces each userThe achieved rate against the target
JMeterOpen Model Thread Group (5.5+, experimental)A plain Thread Group is a closed pool

What is coordinated omission?

It is the error you get when the measuring side stops taking samples because the system is slow, so the samples that go missing are exactly the slow ones. Losing samples at random barely moves a percentile; losing them in step with a slowdown skews all of them.

The name comes from Gil Tene, whose 2013 mailing list post on the problem draws this same line. He is the original author of HdrHistogram, wrk2 lives in his GitHub account, and both projects’ docs explain the effect (checked on 9 October 2026). The k6 docs use the term for a closed workload model that slows its own load down, a common cause; our open vs closed workload model article covers that choice, so this one stays with the measurement.

How does a load test end up hiding slow responses?

A closed-loop generator sends the next request on a connection only after the previous response arrives. When one response takes a second, that connection sends nothing for a second, and the requests it would have sent never get a response time.

The wrk2 README says this of wrk’s model, which times each request from first byte sent to full response: since a connection only sends after a response, the generator coordinates with the server and avoids measuring during high-latency periods (checked on 9 October 2026).

HdrHistogram’s README offers a thought experiment. A system sampled every 10 ms answers in 1 ms for 100 seconds, then stalls for 100 seconds, yielding one 100-second sample. The raw histogram shows about 99.99% of results at 1 ms or below; corrected for the blocked samples, only about half are.

How can you tell if your results have coordinated omission?

Compare the rate you sent with the rate you planned. If the request rate fell while response times rose, the generator backed off and the slow period is under-sampled.

  • The load was set as users or connections with no rate. Any closed loop can do this.
  • The request rate dips where response times climb. A dip in the rate during a spike means requests went unsent.
  • The maximum dwarfs the 99th percentile. A few huge samples among thousands of fast ones is the example above in miniature. Read the whole response time distribution, knowing it only counts requests that were sent.
  • The load generator was short of CPU. LoadFocus documents that an engine near 100% CPU cannot send at the configured rate, and its results show a load generator saturation warning when an engine peaked at or above 80% CPU.

How does wrk2 avoid coordinated omission?

It sends at a constant rate and times each request from when the plan said it should go out. A request that leaves late because its connection was busy is charged for the wait.

wrk2 adds a rate argument (-R, total requests per second) to wrk and records latencies in an HdrHistogram. --u_latency adds the uncorrected histogram, labelled CO, to the report, as in the README’s own example:

wrk -t2 -c100 -d30s -R2000 --u_latency http://127.0.0.1:80/index.html

In the README’s second example, a 1.4-second server pause during a 30-second run made the corrected 99th percentile 200 times the uncorrected one. The README also calls the project experimental and warns that runs under 10 to 20 seconds may not be useful (checked on 9 October 2026). Our HTTP benchmarking tools review compares wrk2 with hey, oha and others.

How does HdrHistogram correct recorded latencies?

If you know the interval at which requests were meant to go out, it adds the samples that a long response blocked. You can correct while recording or afterwards, on a copy.

recordValueWithExpectedInterval records a value and, when it exceeds the interval, adds values stepping down by that interval. copyCorrectedForCoordinatedOmission returns a corrected copy of a finished histogram. The JavaDoc calls the two mutually exclusive (checked on 9 October 2026).

// planned interval: 10 ms, values in microseconds
Histogram h = new Histogram(3);
h.recordValueWithExpectedInterval(latencyUs, 10_000);

// or, after the run, on a raw histogram:
Histogram fixed = raw.copyCorrectedForCoordinatedOmission(10_000);

The correction is only as good as the interval you pass in, so it suits a generator that was meant to send at a steady pace.

How do k6, Gatling, Locust and JMeter handle it?

k6, Gatling and JMeter can start work on a schedule that does not wait for responses. Locust paces each user but cannot start extra users to hold a rate.

k6. In the arrival-rate executors, iterations start independently of system response while a virtual user is free. When none is, k6 skips the iteration and counts it in dropped_iterations, which late in a test may mean the system is degrading (checked on 9 October 2026). A dropped iteration has no response time, so read that counter next to the percentiles. On LoadFocus, k6 scripts run arrival-rate scenarios with a fixed number of users, a closed model, so run k6 yourself when the arrival rate is the point.

Gatling. Steps such as constantUsersPerSec inside injectOpen start new virtual users at a set rate, whether or not earlier ones have finished (checked on 9 October 2026).

Locust. constant_throughput adapts each user’s wait so it runs a task at most a set number of times per second. The docs say wait time can only limit the rate and cannot launch new users, and the API reference adds that a task which overruns its interval gets no wait afterwards, so a slow response still delays that user (checked on 9 October 2026).

JMeter. A Thread Group is a pool of looping threads, a closed loop. JMeter 5.5 added the experimental Open Model Thread Group, which follows a schedule such as rate(1/sec) random_arrivals(2 min) and, per the release notes, spawns threads as needed (checked on 9 October 2026).

Does an open workload model remove coordinated omission?

It removes the main cause, a generator that waits before sending. Two gaps remain: a generator short of users or CPU still falls behind its schedule, and each user in a multi-step journey still waits for its own responses.

The first gap shows up as dropped iterations or a saturated engine; either is a reason to rerun with more headroom. The second is built into most HTTP testing: the wrk2 README notes that sending without waiting only suits non-blocking protocols or one request per connection, which is why wrk2 corrects the timing instead.

FAQ

Who named coordinated omission? Gil Tene, the original author of HdrHistogram, whose wrk2 fork of wrk is built around avoiding it. His 2013 post to the mechanical-sympathy mailing list describes it as a problem he calls by that name.

Is coordinated omission the same as a closed workload model? They are related. A closed model is a common cause, since each virtual user waits for its response before sending again, and the wrk2 README also finds the effect in monitoring code.

Should you correct every latency histogram for it? Only when you know the interval at which requests were planned, because HdrHistogram needs it to fill in the missing samples. Apply one of its two correction methods to a data set, never both.


The technical claims in this article have not been independently reviewed.

LoadFocus team
Written by the LoadFocus team, the people behind a cloud load testing service.