Articles
Locust Interview Questions: User Models, Wait Times, and Distributed Load
Practice Locust interview questions on user models, wait times, distributed workers, and generator limits, with workload calculations and a tested example.
A load test has 1,000 users, no HTTP errors, and a flat throughput graph. Has the service reached capacity? Those numbers cannot answer the question until you know what each user does, how long it waits, and whether the load generator is keeping up.
These Locust interview questions focus on that reasoning. A defensible benchmark connects the intended workload to achieved traffic, business correctness, and generator headroom.
Evidence boundary: Official behavior below follows Locust 2.46.6 documentation, checked September 21, 2026. The interview prompts, calculations, and diagnostic scenarios are original practice exercises. No candidate reports are used, and these questions are not presented as verified questions from a particular employer. The code received a small local smoke test; it is not a production capacity benchmark.
1. What does a Locust user actually represent?
Official fact: Locust creates a user instance running in a gevent greenlet. An HttpUser has an HTTP session that retains cookies. It does not render pages or automatically fetch their images and scripts. A task can contain several sequential requests, with the configured wait applied after the task. Writing a locustfile
Interview application: Describe the user as a modeled actor with a particular journey. An authenticated shopper who browses repeatedly differs from an anonymous client that makes one request and leaves. Both can produce the same user count while stressing different caches, authentication paths, and database records.
Before writing code, define the actor's lifetime, operation mix, data distribution, and success condition. For a catalog test, decide whether shoppers repeatedly read one popular item or spread reads across a large catalog. That choice changes what the experiment can establish.
A useful answer begins: “I would model the journey and session behavior first, then choose the number of active actors needed for the target traffic.” It should also identify what the test excludes, such as JavaScript execution or browser rendering time.
2. Why are users, spawn rate, and RPS different?
Official fact: The --users setting controls the target user count; --spawn-rate controls how quickly users start. Neither is an HTTP request-rate setting. Configuration reference
Original exercise: Suppose every task makes two sequential requests. Their mean durations are 0.2 and 0.3 seconds, followed by a 1.5-second wait. Ignore startup, retries, and client overhead for this illustrative steady-state calculation.
| Quantity | Calculation | Result |
|---|---|---|
| Task execution time | 0.2 + 0.3 seconds | 0.5 seconds |
| Complete user cycle | 0.5 + 1.5 seconds | 2 seconds |
| Journey throughput with 100 users | 100 / 2 | 50 journeys/second |
| Request throughput | 50 × 2 | 100 requests/second |
| Approximate mean requests in flight | 100 RPS × 0.25-second mean request duration | 25 requests |
Only part of the user population is issuing requests at any instant. Sleeping users still count as users.
Now let combined request time rise to 2.5 seconds while the wait remains 1.5 seconds. The cycle becomes four seconds, yielding about 25 journeys and 50 requests per second. The service gets slower while the closed user population sends less traffic.
That is the key follow-up: a fixed population can reduce offered traffic as responses slow. If the requirement is “new work continues arriving at 100 journeys per second regardless of latency,” this simple closed-user model does not represent it. Explain how you would implement and verify an independent arrival schedule, including late or missed starts, rather than silently treating concurrency as arrival rate.
3. Which wait strategy matches the workload?
Official fact: constant(2) adds a fixed wait, while between(1, 3) chooses a wait within a range. constant_pacing(2) adjusts the wait to target a two-second task cycle. constant_throughput(0.5) expresses the corresponding task rate per user. When execution consumes the interval, waiting cannot restore the requested rate. Wait-time API
Original decision exercise: For a person reading product details, a variable pause may represent thinking time. For a device polling on a cadence, pacing may better match the requirement. Neither choice should be justified merely because it produces a convenient graph.
With a half-second task, a two-second fixed wait gives a 2.5-second cycle. Two-second pacing instead leaves roughly 1.5 seconds to wait. If the task takes three seconds, the pacing budget is already exhausted. State the achieved rate separately from the configured target.
The unit matters as much as the value. A task containing two requests creates two samples per successful iteration. A task that returns early after a failed prerequisite creates fewer. Check observed request counts against completed journeys before explaining a surprising RPS result.
4. How do you preserve order and detect false success?
Official fact: Weighted tasks are randomly selected; weights do not define a workflow order. For explicit sequences, Locust also provides SequentialTaskSet. Task selection, TaskSet documentation
For a short ordered journey, one task with ordinary sequential Python is easy to inspect. This original example reads a catalog and then a known item. The catalog read is independent; a real create-then-read journey would extract and validate the created identifier before continuing.
from locust import HttpUser, task, constant
from uuid import uuid4
class CatalogUser(HttpUser):
wait_time = constant(1)
def on_start(self):
self.client.headers['X-Test-User'] = str(uuid4())
@task
def browse(self):
self.client.get('/catalog', name='/catalog', timeout=2)
with self.client.get('/items/42', name='/items/[id]',
catch_response=True, timeout=2) as response:
if response.status_code != 200:
response.failure('item HTTP failure')
return
try:
item = response.json()
except ValueError:
response.failure('invalid JSON')
return
if not isinstance(item, dict) or item.get('id') != 42:
response.failure('wrong item')
Official fact: name controls statistics grouping, and catch_response lets a response's content determine success or failure even when its status is 200. HTTP client API
Local verification: Using Locust 2.46.6, two five-second runs exercised four users against a loopback HTTP fixture. The valid run recorded 24 requests with zero failures. The wrong-item run recorded 32 requests, including 16 item samples that all failed despite HTTP 200; catalog requests remained successful. Both runs produced the intended two request groups and four distinct user headers. The failing run exited nonzero.
The header is only a local identity marker, not authentication. For an authenticated workload, allocate real test identities and preserve session state per user. Avoid accidentally routing every shopper through the same account or cart unless that contention is the experiment.
5. How would you run a meaningful headless test?
For the example above, a short local run could use:
locust -f locustfile.py --headless \
--host http://127.0.0.1:8000 \
--users 4 --spawn-rate 4 --run-time 5s \
--stop-timeout 2 --csv smoke
A fixture implementing those endpoints must already be listening at that address.
Official fact: Headless run time starts with the test, not when ramp-up finishes. A stop timeout gives executing tasks time to finish. Locust supports custom exit criteria for headless runs, so CI can evaluate more than whether requests failed. Headless execution
Interview application: Write the acceptance rule before looking at the result. Specify the steady interval, required achieved traffic, acceptable business-failure rate, and latency threshold for the important operation. A passing latency number at half the required traffic does not establish the original objective.
Keep warm-up separate from measurement. If startup includes account creation and cache population, say whether those costs belong in the experiment. Retain the script version, fixture or dataset version, client configuration, and server configuration so another engineer can explain differences between runs.
Consider an original checkout scenario: 1,000 journeys begin, but 200 fail during authentication. A purchase endpoint showing excellent latency for the remaining 800 journeys does not demonstrate that all customers could check out. Report attempted journeys, failed prerequisites, and completed purchases together. Decide whether retries count toward the customer success deadline, and avoid reporting each retry as a new customer.
A second trap is request latency versus journey latency. If a journey calls three services in sequence, a percentile from one endpoint cannot describe the complete customer experience. Define the journey boundary and measure it explicitly if that is the acceptance criterion. Keep its transaction metric distinct from HTTP request samples so a combined count does not accidentally double the apparent traffic.
Do not average worker P95 values to produce a global P95. As a mathematical matter, percentiles depend on the combined distribution and sample counts. Also inspect endpoint-level results: a frequently called fast catalog endpoint can obscure a much slower purchase operation in aggregate summaries.
6. What changes when Locust runs on multiple workers?
Official fact: In distributed mode, the master coordinates workers and receives their statistics; workers run the users and generate traffic. The requested user count is distributed across workers. Headless runs can use --expect-workers to wait for the intended worker population. Distributed load generation
Original design exercise: You have 600 accounts and three worker processes. Each process reading the same file from its first line can allocate overlapping accounts. A module-level counter does not coordinate separate processes. Assign disjoint account partitions or use an allocation service whose behavior you can verify.
Likewise, a local setup hook should not be assumed to run exactly once for the entire cluster. Decide who owns dataset preparation and who owns per-user initialization. Record account allocation separately from request statistics so unexpected collisions are diagnosable.
Scaling out also changes the experiment's network paths and source addresses. Check whether rate limits are per account, per address, or global. If workers receive different limits, a higher aggregate rate may reflect a changed traffic identity rather than improved server capacity.
Before comparing one-worker and three-worker results, hold total users, task mix, and data distribution constant. Then change concurrency in a separate experiment. Changing both at once makes the cause of an improvement harder to identify.
7. Is the service saturated, or is the generator falling behind?
Official fact: Locust documents CPU warnings and a more efficient FastHttpUser client that reduces HTTP client CPU overhead. Its custom-protocol guidance also warns that incompatible blocking libraries can prevent cooperative concurrency. HTTP client performance, Testing other protocols
Original diagnostic matrix: Treat each observation as evidence for a next experiment, not a complete diagnosis.
| Observation | Plausible explanation | Useful next check |
|---|---|---|
| Worker CPU is high; service has spare capacity | Client processing limits generated traffic | Profile client work; compare the same workload with more generator capacity |
| Workers have headroom; server queues and latency rise | Service or downstream bottleneck | Correlate queue depth, database waits, and endpoint latency |
| Server sees fewer requests than the client expects | Network, connection limits, or client scheduling | Compare request counts and connection failures along the path |
| Failures rise only for shared accounts | Test-data contention or an account limit | Repeat with verified distinct identities |
| Low latency accompanies an unexpectedly low request rate | Waiting, early task returns, or under-generation | Reconcile user cycles, completed journeys, and sample counts |
One controlled comparison is especially useful: keep the total workload unchanged and add generator capacity. If achieved traffic changes materially, investigate the generation side before announcing a service ceiling. Preserve the original client implementation when possible; changing clients can introduce another variable.
An apparently healthy aggregate CPU value is insufficient. Inspect individual workers and the resources they depend on. A single busy process, constrained network path, or expensive response parser can limit the test while other machines remain idle.