Performance testing and JMeter interview questions
Updated 2026-11-13 · 18 min read
Thirty questions on performance testing and Apache JMeter, from what a percentile means to finding a bottleneck. The JMeter plan and commands were run against the free ShopLite app with JMeter 5.6.3.
Performance interviews check two things: whether you understand what you are measuring, and whether you can build a JMeter test that behaves like real users. Freshers get the definitions and JMeter elements; experienced candidates get "the p95 doubled after the release, what do you do?" This page covers both.
Performance testing basics
1. What is performance testing, and what questions does it answer?
Testing how fast and how stable a system is under a given load, and how much load it can take. The questions are business ones: can checkout handle the expected sale-day traffic with 95 percent of requests under the agreed time, where does it break, what breaks first, and does it recover. A functional test asks "does it work"; a performance test asks "does it still work for many users at once, quickly enough".
2. What are the main types of performance test?
- Load test: the expected peak load, to check the agreed targets are met.
- Stress test: beyond the expected load, to find the breaking point and how it fails.
- Spike test: a sudden jump in users (a flash sale opening, a Tatkal-style booking window).
- Soak or endurance test: normal load for hours, to find memory leaks, filling disks and connection pool exhaustion.
- Scalability test: adding load step by step (or adding servers) to see how capacity grows.
- Volume test: large amounts of data, such as a table with millions of orders.
Teams use these names loosely, so say what load shape you mean. There is a fuller comparison on load vs stress vs spike testing.
3. Which metrics do you report?
Response time (as percentiles, not only the average), throughput (requests or transactions per second), error rate, and concurrency (active users or threads). On the server side: CPU, memory, garbage collection pauses, database time and connection pool usage, and queue lengths. A result without the matching server metrics tells you that something is slow but not why.
4. Why use percentiles instead of the average response time?
An average hides the slow requests. If 90 requests take 200 ms and 10 take 5 seconds, the average is 680 ms, which describes nobody's experience, while the 95th percentile shows that some users wait 5 seconds. The p95 means 95 percent of requests were at or below this time. Targets are usually written as percentiles ("p95 of search under 1 second at 200 requests per second").
Likely follow-up: Are percentiles always reliable? Not with few samples. In my run, JMeter's report gave the 90th percentile of 10 login requests as 44.3 ms while a simple nearest-rank calculation gave 11 ms, because one of the ten was slow and the two methods interpolate differently. With small counts, report the max and the raw values, and run longer.
5. What is the difference between response time, latency and connect time in JMeter?
From the JMeter glossary: elapsed time runs from just before sending the request to just after the last byte of the response; latency runs to just after the first part of the response; connect time is the time to set up the connection, including the TLS handshake. Connect time is not subtracted from latency. JMeter does not render pages or run their JavaScript, so its elapsed time is not what a user sees in a browser.
6. There are no performance requirements. How do you start?
Ask for data instead of guessing: production analytics or server logs (peak requests per minute, busiest pages, the share of each user journey), business plans (expected sale-day traffic), and what "too slow" means to the product owner. Turn that into a workload model and written targets, and get them agreed before testing. If nothing exists, test the current release as a baseline and compare every later release against it.
7. How do you build a workload model? What is Little's Law?
List the user journeys and their mix (for example 70 percent browse, 20 percent search, 10 percent checkout), the target throughput, and the think time between steps. Little's Law links them: concurrent users = throughput × (response time + think time). If you need 50 journeys per second and each journey cycle takes about 5 seconds including think time, you need about 250 concurrent users. This is why "1,000 users" means little until you also say how often each user acts.
8. Why must the test environment be close to production?
Results do not scale in a straight line. Half the servers does not mean half the capacity, because the database, caches, network and third-party services behave differently under load. Record what differs (data volume, instance sizes, mocked payment gateway) and say so in the report. Never run a load test against production or a shared environment without agreement from the people who own it.
JMeter fundamentals
9. What is JMeter, and what does it not do?
Apache JMeter is an open-source Java tool that generates load at the protocol level: it sends HTTP requests (and JDBC, JMS, TCP and others) and measures the responses. It is not a browser: it does not run the page's JavaScript or render anything, and it fetches embedded resources only if you ask it to. So it measures server-side performance; front-end performance needs browser tools.
10. What are the main elements of a JMeter test plan?
- Thread group: the virtual users, with their count, ramp-up and loop count or duration.
- Samplers: the requests (HTTP Request, JDBC Request).
- Logic controllers: the flow (Loop, If, Once Only, Transaction controllers).
- Config elements: shared settings and data (HTTP Request Defaults, Header Manager, Cookie Manager, CSV Data Set Config).
- Pre- and post-processors: work before or after a sampler; post-processors usually extract values.
- Timers: pauses before samplers.
- Assertions: pass or fail checks on responses.
- Listeners: show or save results.
The plan used for this page, as JMeter shows it:
Test Plan: ShopLite browse and cart
└── Thread Group "Shoppers" (threads ${__P(threads,2)}, ramp-up ${__P(rampup,2)}, loops ${__P(loops,3)})
├── HTTP Request Defaults (host ${__P(host,localhost)}, port ${__P(port,3001)})
├── HTTP Header Manager (Content-Type: application/json, Authorization: Bearer ${token})
├── CSV Data Set Config (users.csv -> email, password)
├── Once Only Controller "Log in once per user"
│ └── POST /api/auth/login {"email":"${email}","password":"${password}"}
│ └── JSON Extractor token = $.token
├── Transaction Controller "Browse and open cart"
│ ├── GET /api/products?q=shoes&limit=5
│ └── GET /api/cart
│ ├── Response Assertion (response code equals 200)
│ └── Duration Assertion (1000 ms)
└── Constant Timer (500 ms think time)
11. In what order does JMeter run the elements, and what is scoping?
For each sampler, JMeter applies config elements, then pre-processors, timers, the sampler itself, post-processors, assertions and finally listeners. Samplers and logic controllers run in tree order. Everything else works by scope: an element applies to the samplers in its branch of the tree. In the plan above, the timer sits at thread-group level, so it pauses before every request; the assertions sit under "GET cart", so they check only that request.
Likely follow-up: Where is the common mistake? Putting a timer or assertion at a level where it applies to more requests than intended. A one-second timer at the top of a plan with ten requests per journey adds ten seconds per journey.
12. How do threads, ramp-up and loops work?
Threads are virtual users. Ramp-up is the time JMeter takes to start all of them: the manual's example is 10 threads with a 100-second ramp-up, so a new thread starts every 10 seconds (the first starts at once, so the tenth starts at 90 seconds). Loop count is how many times each thread runs the plan; alternatively, tick "Specify thread lifetime" and give a duration. A ramp-up of 0 starts everyone at once, which is a spike test whether you meant one or not.
13. Why run JMeter in CLI mode, and what is the command?
The GUI uses memory and CPU that the load test needs, and the manual says plainly that GUI mode is for building and debugging scripts, not for load testing. The command I ran:
jmeter -n -t shoplite.jmx -l results.jtl -e -o report -Jthreads=10 -Jrampup=10 -Jloops=20
-n CLI mode, -t the plan, -l the results file, -e build the HTML report at the end, -o the report folder, -J set a property. The run printed a running summary line every few seconds and ended with summary = 410 in 00:00:30 ... Err: 0 (0.00%) against ShopLite.
14. Which listeners do you use during a load test?
As few as possible. Write raw results to a file with -l and build reports afterwards. "View Results Tree" stores every request and response and should be used only while writing and debugging a script; the best-practices page says not to use it or "View Results in Table" during the load test.
15. How do you produce the HTML dashboard report?
Either at the end of a run with -e -o <folder>, or later from an existing results file:
jmeter -g results.jtl -o report2
The report folder must be empty or not exist. When I re-ran into the same folder, JMeter stopped with An error occurred: Cannot write to '/work/report' as folder is not empty and exit code 1. Adding -f deletes the old results file and report folder before the run. The report includes statistics per request with three configurable percentiles (90, 95 and 99 by default, in 5.6.3), an APDEX table, errors and graphs over time.
16. What are timers for, and how do you control throughput?
Real users pause between actions, so a plan without timers sends requests back to back and overstates the load per user. The Constant Timer gives a fixed pause; the Uniform Random and Gaussian Random timers add variation. To aim for a fixed rate instead of a fixed pause, use the Constant Throughput Timer (target in samples per minute, spread over this thread or all active threads) or the Precise Throughput Timer. A throughput timer only slows threads down; if there are too few threads or the server is slow, you will not reach the target.
17. Which assertions do you use in a load test, and what do they cost?
A Response Assertion on the status code, a check that the body contains something only a correct page has (an order id, not the error page that also returns 200), and a Duration Assertion to mark slow responses as failed. Keep them light: assertions run for every sample, and many heavy ones (large regular expressions, XPath on big documents) use load-generator CPU that the test needs.
Scripting realistic tests
18. What is correlation, and how did you do it?
Capturing a dynamic value from one response (a session token, a CSRF token, an order id) and sending it in later requests. Without it, every virtual user reuses the value recorded once, and the requests fail or test the wrong thing. In the ShopLite plan, a JSON Extractor under the login request reads $.token into a variable token, and the Header Manager sends Authorization: Bearer ${token}. For HTML or headers, use the Regular Expression Extractor (template $1$ for the first group) or the Boundary Extractor. Set a default value such as NOT_FOUND so a failed extraction is obvious in the results.
19. How do you give each virtual user different data?
CSV Data Set Config. A line is read at the start of each iteration, and by default each thread gets a different line (which thread gets which line can vary between runs). The values go into the variables you name (or the names in the file's first line if you leave them blank). The sharing mode decides who shares the file: all threads (the default), the current thread group, each thread separately, or threads with the same identifier. "Recycle on EOF" starts the file again at the end (default true); with recycle off, "Stop thread on EOF" ends a thread when the data runs out.
Likely follow-up: What if two threads log in as the same user? It depends on the app. Some apps log the first session out, carts collide, and one-time actions fail. Give each concurrent thread its own account when the app has per-user state.
20. What is the difference between JMeter variables and properties? How do you parameterise a plan?
Variables belong to one thread; properties are global to the JMeter process and can be set on the command line with -J. That is why a plan reads its load settings through the __P function, for example ${__P(threads,2)}: the default is 2, and -Jthreads=10 overrides it without editing the plan. Use the same for host, port and duration so one .jmx runs against QA, staging or a CI container.
21. What does a Transaction Controller do?
It records an extra sample covering all the requests inside it, so you can report on a user action ("browse and open cart") as well as on single requests. By default its time excludes timers and pre- and post-processor time; a checkbox includes them. It is successful only if every sample inside it succeeded. In my report the dashboard's Total row counted the 410 requests and not the 200 transaction samples, so read totals carefully when transactions are in the plan.
22. How do you record a script, and what do you clean up afterwards?
With the HTTP(S) Test Script Recorder: JMeter acts as a proxy, you click through the journey in a browser configured to use it (and trust JMeter's certificate for HTTPS), and requests appear in the plan. Then clean up: remove analytics, ads and other third-party calls, group requests into transactions, add correlation for every dynamic value, replace hard-coded data with CSV variables, and add assertions and timers. A raw recording replays one user's session and is not yet a load test.
23. What do the HTTP Cookie Manager and Cache Manager do?
The Cookie Manager stores and sends cookies per thread, as a browser would, so cookie-based sessions work. The Cache Manager imitates the browser cache for embedded resources. Without a Cookie Manager, a cookie-based login works for one request and then the user appears logged out. ShopLite uses a bearer token in a header, which is why its plan needs a Header Manager instead.
24. Which logic controllers do you use most?
Once Only Controller (log in once per thread), Loop Controller, If Controller (only when a condition holds, such as an extracted value being present), Throughput Controller (send only a percentage of users down a path, to build the journey mix), Transaction Controller, and Module or Include Controller to reuse fragments.
25. When do you write a script in JMeter, and in which language?
When a request needs logic the built-in elements do not provide: building a signature, generating a value, complex extraction. Use the JSR223 elements with Groovy and keep "cache compiled script" on. The component reference recommends moving from BeanShell to JSR223 with Groovy for performance. Keep scripts small; logic-heavy scripts make the load generator the bottleneck.
Running at scale and analysing results
26. How does distributed testing work in JMeter?
One JMeter client controls several JMeter server machines that generate the load. The client sends the plan to every server; each server runs the full thread count, so 100 threads on 4 servers is 400 users. Every machine needs the same JMeter and Java versions, CSV files and plugins must be copied to each server, and RMI between them uses SSL by default since JMeter 4.0 (you create the keystore, or switch it off on a trusted network). Start a run with -R server1,server2. Watch the network between servers and the system under test, since it can limit you before the application does.
27. How do you find a bottleneck from the results?
Increase load in steps and watch where throughput stops rising while response times climb: that knee point is the capacity. Then correlate with server metrics at that time: which resource saturated (CPU, database connections, a thread pool, a slow query, garbage collection pauses), and which transaction degraded first. Errors such as timeouts and 503s usually appear just after the knee. Report it as "search stops scaling at about N requests per second; database CPU is at its limit; the slowest query is X", not as a list of graphs.
Likely follow-up: How do you know the load generator is not the bottleneck? Watch its own CPU, memory and network during the run. If the generator's CPU is near its limit, or response times rise while the server is idle, add generators or simplify the script (fewer listeners and assertions, cache compiled scripts).
28. Response times are fine in the test but users complain in production. Why?
The test did not match reality: different data volume (a test database with a thousand orders, production with millions), missing journeys or a wrong mix, cache always warm because every user searched the same word, third-party services mocked, network distance and mobile networks not included, or JMeter measuring the server while users wait for front-end rendering. Compare the workload model with production logs, and check front-end timings separately.
29. How do you analyse a JTL file yourself?
The CSV results file has one row per sample, with columns such as label, elapsed and success. A short script gives per-request numbers when you want something the dashboard does not show:
import csv
import math
import sys
from collections import defaultdict
def percentile(sorted_values, pct):
"""Nearest-rank percentile: the smallest value with at least pct% of samples at or below it."""
rank = math.ceil(pct / 100 * len(sorted_values))
return sorted_values[max(rank, 1) - 1]
times = defaultdict(list)
errors = defaultdict(int)
with open(sys.argv[1], newline="") as f:
for row in csv.DictReader(f):
times[row["label"]].append(int(row["elapsed"]))
if row["success"] != "true":
errors[row["label"]] += 1
print(f"{'label':<22}{'count':>6}{'avg':>6}{'p90':>6}{'p95':>6}{'max':>6}{'err%':>7}")
for label, values in sorted(times.items()):
values.sort()
avg = sum(values) / len(values)
err = 100 * errors[label] / len(values)
print(f"{label:<22}{len(values):>6}{avg:>6.0f}{percentile(values, 90):>6}{percentile(values, 95):>6}{values[-1]:>6}{err:>7.1f}")
Run with python3 p90.py results.jtl. On my ShopLite run its numbers matched the dashboard for the requests with 200 samples each and differed for the 10 login samples, as described in question 4. Different tools calculate percentiles differently; say which one you used when you compare releases.
30. How would you add performance checks to a CI pipeline?
Not a full load test on every pull request: it is slow, needs a production-like environment and gives noisy results on shared CI machines. Instead, run a short, small-load smoke test (a few users for a few minutes) on every deploy to a test environment, fail the build on errors or on a p95 far above the stored baseline, and keep the trend over builds. Run the full load, stress and soak tests on a schedule or before big releases. Script-first tools such as k6 fit this style well; see JMeter vs k6.
Quick quiz
- A thread group has 20 threads and a 60-second ramp-up. Roughly how often does a new thread start?
- Which mode should a load test run in: GUI or CLI?
- You extracted a token with a JSON Extractor, but later requests send the literal text
NOT_FOUND. What happened? - A Constant Timer of 2 seconds sits directly under the thread group, which has 5 requests. How much think time does one iteration add?
- Why is the average a poor summary of response time?
Answers
- Every 3 seconds (60 / 20). The first thread starts immediately.
- CLI (
jmeter -n ...). The GUI is for building and debugging. - The extraction failed (wrong JSON path, or the login itself failed), so the default value was used. Check the login response.
- About 10 seconds: the timer is in scope of all five requests and runs before each.
- A few very slow requests disappear into it. Use percentiles and the max.
Practise it
Run the free ShopLite app on your own machine and build the plan from question 10: log in once per user from a CSV, correlate the token, browse and open the cart, then run it in CLI mode with the HTML report. Raise the threads step by step and watch the report. Then try a JMeter test that makes the same requests as one of your API tests from the API testing questions, and compare what each one tells you.
Quick answers
Which JMeter version does this page describe?
JMeter 5.6.3, the release offered on the Apache download page when this was written, run on Java 21. Element names and defaults can differ in other versions.
Can I load test a website I do not own to practise?
No. Load testing someone else's system without permission can harm it and may be illegal. Practise against an app you run yourself, such as ShopLite on your own machine.
Do I need to know a performance tool other than JMeter?
Check the job description. JMeter is common in service companies; some product teams use k6, Gatling or Locust. The concepts on this page (workload, percentiles, correlation, bottlenecks) carry over to all of them.
Sources
- Apache JMeter user manual: getting started and CLI options (official, accessed 2026-11-13)
- Apache JMeter: elements of a test plan, execution order and scoping (official, accessed 2026-11-13)
- Apache JMeter component reference (official, accessed 2026-11-13)
- Apache JMeter: generating the dashboard report (official, accessed 2026-11-13)
- Apache JMeter best practices (official, accessed 2026-11-13)
- Apache JMeter remote (distributed) testing (official, accessed 2026-11-13)
- Apache JMeter glossary (official, accessed 2026-11-13)
Want a project you can show in interviews?
The portfolio project kit walks you through testing a deliberately buggy app with Selenium or Playwright and API tests, then explaining it. The app itself is free.
