QA Interview
k6 Scripting Interview Questions for Performance Testers (2026)
Practice k6 scripting interview questions for performance testers with 48 specific answers on scenarios, checks, thresholds, data, metrics, and debugging.
23 min read | 4,476 words
TL;DR
Strong k6 interview answers connect JavaScript code to a defensible workload model. Be ready to write lifecycle functions, scenarios, checks, thresholds, correlation, custom metrics, and data parameterization, then explain how you would validate the generator and interpret latency, errors, and throughput.
Key Takeaways
- Explain k6 execution in terms of virtual users, iterations, scenarios, executors, and lifecycle functions.
- Separate checks, which record correctness, from thresholds, which decide the process exit result.
- Select executors from the workload model instead of forcing every test into a fixed VU loop.
- Keep setup data shareable and immutable, and use SharedArray for large read-only fixtures.
- Correlate dynamic values, parameterize identities, and validate both HTTP status and business behavior.
- Treat custom metrics, tags, summaries, and observability exports as part of script design.
- Discuss load generation limits, test data, environment safety, and result interpretation alongside code.
These k6 scripting interview questions for performance testers prepare you to explain not only syntax, but also why a script represents real production traffic. A credible answer connects k6 code to workload shape, business correctness, service-level objectives, test data, and trustworthy analysis.
The 48 questions below move from execution basics to scenarios, correlation, metrics, debugging, and test design. The examples use the current k6 module imports and are complete enough to save as a file and run with k6 run script.js. For a structured first project, review the k6 load testing tutorial, then use this guide to practice explaining each decision aloud.
TL;DR
| Interview area | What a strong answer demonstrates |
|---|---|
| Script lifecycle | Correct use of init, setup, default or scenario functions, teardown, and handleSummary |
| Workload modeling | A reasoned choice of executor, VUs, arrival rate, stages, duration, and graceful stop |
| Validation | Business checks plus thresholds that fail automation on unacceptable results |
| Data and state | Safe parameterization, correlation, per-VU state, SharedArray, and environment configuration |
| Analysis | Interpretation of percentiles, throughput, errors, dropped iterations, tags, and custom metrics |
| Engineering quality | Small reusable modules, bounded logging, versioned scripts, generator monitoring, and reproducibility |
Use the table as a topic map, not a memorization sheet. Interviewers usually follow a definition with a design change, failure symptom, or short coding task.
1. k6 Scripting Interview Questions for Performance Testers: Execution Basics
Q: What is k6, and why would a performance team choose it?
k6 is a load-testing engine whose tests are written in JavaScript and executed by a purpose-built runtime rather than Node.js. Teams choose it for scriptable HTTP and protocol testing, explicit workload executors, built-in metrics, thresholds, and automation-friendly exit codes. Its scripts fit source control and CI review well because workload, validation, and pass criteria live together. I would still evaluate protocol coverage, distributed execution needs, and team skills before selecting it over another tool.
Q: Describe the k6 test lifecycle.
Code in init context runs once per VU initialization and is where imports, options, and reusable definitions belong. setup() runs once for the test and may return JSON-serializable data to scenario functions and teardown(). A default or named scenario function executes repeatedly according to its executor. teardown() performs one final cleanup, while handleSummary() can format end-of-test output.
Q: What belongs in init context, and what should not be there?
Put module imports, options, SharedArray construction, static helper functions, and metric declarations in init context. Network requests are not allowed there because initialization must remain deterministic across local and distributed generators. Credentials should normally enter through environment variables rather than hard-coded constants. Large fixture parsing belongs in SharedArray so every VU does not allocate a separate copy.
Q: How does a VU execute JavaScript?
Each VU has an isolated JavaScript runtime and repeatedly calls its assigned scenario function. A VU preserves its own global state between its iterations, but it does not share mutable JavaScript objects with other VUs. That makes a VU suitable for a continuing user session, although scripts must deliberately reset data when iterations should be independent. The scheduler, executor, response time, and sleeps determine how frequently closed-model VUs begin new iterations.
2. Script Structure and JavaScript Runtime
Q: Can k6 run any Node.js package?
No. k6 does not execute scripts in Node.js, so packages that depend on Node built-ins such as fs, net, or child_process will not work. JavaScript bundles may work when their dependencies use supported language and web APIs, but compatibility must be tested rather than assumed. Prefer official k6 modules, supported extensions, and lightweight pure JavaScript utilities. This distinction prevents the common interview mistake of proposing runtime file access from a VU.
Q: Write the smallest useful k6 HTTP test.
A useful smoke script sends a request, checks correctness, and defines an acceptance threshold. Saving this as smoke.js and running k6 run smoke.js produces both HTTP metrics and a meaningful exit result.
import http from 'k6/http';
import { check } from 'k6';
export const options = {
vus: 1,
iterations: 1,
thresholds: {
http_req_failed: ['rate==0'],
http_req_duration: ['p(95)<500'],
},
};
export default function () {
const response = http.get('https://test.k6.io/');
check(response, {
'status is 200': (r) => r.status === 200,
'home page returned': (r) => r.body.includes('Collection of simple web-pages'),
});
}
The content check catches a fast error page that a status-only assertion could miss. The illustrative 500 ms threshold must be replaced with the tested system's objective.
Q: How do you pass configuration into a k6 script?
Read environment values through __ENV, for example const BASE_URL = __ENV.BASE_URL || 'https://test.k6.io'. Supply them with k6 run -e BASE_URL=https://staging.example.com script.js; remember that ordinary host environment variables are not automatically exposed unless passed or included by the execution environment. Validate required values early and avoid printing secrets. Keep non-secret workload defaults in versioned options so a run can be reproduced.
Q: When should you split a k6 script into modules?
Split modules when business flows, request clients, configuration, or validation helpers have independent reasons to change. A checkout flow should read like a user journey rather than a wall of headers and parsing code. Keep metric declarations and options discoverable, and avoid abstraction that hides which requests a transaction performs. Module boundaries should improve review and reuse without concealing load-generating behavior.
3. Scenarios, Executors, and Workload Models
Q: What is the difference between a closed and open workload model?
A closed model controls concurrent VUs, so slower responses reduce the rate at which iterations start. An open model schedules new iterations at a target arrival rate independently of response time, adding initialized VUs up to configured limits. Closed models suit a bounded pool of active users; open models suit externally arriving work such as orders or webhook calls. Choosing between them changes the question the test answers.
Q: When would you use constant-vus?
Use constant-vus when you need a stable number of concurrent looping users for a fixed duration. It is effective for soak tests, capacity comparisons, or workloads whose population is naturally bounded. Throughput is an outcome, not an input, because iteration duration controls how fast each VU loops. Include realistic think time if the modeled users pause between actions.
Q: When is ramping-vus appropriate?
ramping-vus gradually changes concurrency through stages, which makes it useful for warm-up, stepped load, and recovery observation. It can reveal where queues grow as active users increase, but it does not guarantee a request rate. I would define stage durations long enough for the system to stabilize and pair the scenario with clear tags or external annotations. Abruptly ending the final stage can hide recovery, so a ramp-down period is often valuable.
Q: Explain constant-arrival-rate and preAllocatedVUs.
constant-arrival-rate starts iterations at a fixed rate, such as 20 per second, throughout the scenario. preAllocatedVUs reserves enough workers to begin that rate without runtime allocation, while maxVUs sets an optional ceiling for additional workers when iterations take longer. If the engine reaches the ceiling, dropped_iterations shows scheduled work it could not start. The VU calculation must include expected iteration time and safety margin, not just the target rate.
Q: How would you model two business flows with different traffic shares?
Create two named scenarios with separate functions and arrival rates derived from the same production window. If browse traffic is 80 per second and checkout traffic is 5 per second, encode those rates directly instead of randomly branching inside one VU loop. Separate scenarios allow independent tags, thresholds, start times, and VU allocation. The k6 scenarios and executors guide covers the workload implications in more depth.
import http from 'k6/http';
export const options = {
scenarios: {
browse: { executor: 'constant-arrival-rate', exec: 'browse', rate: 80, timeUnit: '1s', duration: '2m', preAllocatedVUs: 30 },
checkout: { executor: 'constant-arrival-rate', exec: 'checkout', rate: 5, timeUnit: '1s', duration: '2m', preAllocatedVUs: 10 },
},
};
export function browse() { http.get('https://test.k6.io/', { tags: { flow: 'browse' } }); }
export function checkout() { http.get('https://test.k6.io/my_messages.php', { tags: { flow: 'checkout' } }); }
4. Checks, Thresholds, and Acceptance Criteria
Q: What is the difference between a check and a threshold?
A check evaluates a condition for an individual response and records a pass or fail rate, but a failed check alone does not necessarily fail the k6 process. A threshold evaluates an aggregate metric over the run and makes the test exit unsuccessfully when the criterion is violated. For example, a response status check can feed the checks metric, while checks: ['rate>0.99'] defines the release gate. Mature scripts use both because diagnostics and acceptance serve different purposes.
Q: How would you define a latency service-level objective?
Translate the agreed objective into one or more percentile thresholds, such as p(95)<400 and p(99)<900, using the same scope and measurement boundary as the requirement. Avoid using only average latency because a small slow tail can be hidden. Add an error-rate criterion so fast failures cannot satisfy the latency gate. Confirm whether the objective covers all requests, one endpoint, or an end-to-end transaction before coding it.
Q: How do tagged thresholds isolate one endpoint or flow?
Attach a stable tag to relevant requests, then use a submetric threshold such as 'http_req_duration{flow:checkout}': ['p(95)<700']. Tags should describe bounded business dimensions, not unique user IDs, because high cardinality increases metric cost. A scoped threshold prevents a large volume of fast browse calls from masking slow checkout calls. The exact selector must match the tag key and value emitted by the script.
Q: What does abortOnFail do in a threshold?
abortOnFail: true requests test abortion after a threshold becomes known to be failing, subject to its evaluation behavior. delayAbortEval can postpone evaluation through warm-up so early cold-start samples do not stop the run. Use early abort for protective limits or obviously invalid tests, not as a reflex for every percentile. A capacity test may need to continue after degradation to observe the failure curve and recovery.
Q: Why can a test pass its checks but still be invalid?
Checks can all pass while the generator misses the requested arrival rate, uses the wrong data, hits a cache-only path, or overloads its own CPU. A 200 response may also contain a business error unless content is verified. Review dropped_iterations, iteration rate, request counts, data uniqueness, generator resources, and server telemetry alongside checks. Validity is evidence that the intended workload reached the intended system, not merely a green percentage.
For more acceptance examples, see k6 thresholds and checks.
5. HTTP Requests, Correlation, and Sessions
Q: How do you send JSON in a POST request?
Serialize the object, set the content type, and validate the response contract. The code should make payload construction visible so reviewers can spot unrealistic data.
import http from 'k6/http';
import { check } from 'k6';
export default function () {
const payload = JSON.stringify({ name: `user-${__VU}-${__ITER}` });
const response = http.post('https://test.k6.io/user/register/', payload, {
headers: { 'Content-Type': 'application/json' },
tags: { operation: 'register' },
});
check(response, { 'accepted response': (r) => r.status >= 200 && r.status < 300 });
}
For a real API, use the documented route and assert a returned identifier or schema field. Unique VU and iteration values reduce accidental collisions, but they do not guarantee uniqueness across distributed instances.
Q: What is correlation in a performance script?
Correlation extracts a dynamic value from one response and supplies it to a later request in the same business flow. Common examples are access tokens, CSRF values, order IDs, and continuation cursors. Parse JSON with response.json('path'), use a supported HTML parser for markup, and fail the iteration cleanly when the value is absent. Hard-coding a captured token makes the script fragile and may bypass the workflow being measured.
Q: How would you handle authentication tokens?
Acquire tokens in the place that matches real behavior: setup() for one shared technical token, per VU for long-lived user sessions, or inside an iteration when every journey logs in. Cache and refresh according to token lifetime rather than requesting a token before every business call by habit. Keep secret client credentials in injected environment variables. Tag authentication separately so token latency and errors do not distort the protected endpoint without visibility.
Q: Does k6 maintain cookies automatically?
Each VU has a cookie jar, so cookies set by a response are normally sent on matching later requests for that VU. http.cookieJar() gives explicit access when a script must inspect, set, or clear cookies. Because the jar persists across iterations, clear or replace session state when every iteration should represent a new user. Never assume cookies cross between VUs.
Q: How do you group requests into a business transaction?
Use group('checkout', () => { ... }) to organize nested requests and create the group system tag. Groups improve result slicing, but their duration includes JavaScript work and sleeps inside the callback, so it is not automatically a pure server transaction timer. Use a Trend when you need an explicitly measured business duration with controlled start and stop points. Keep group nesting shallow enough that output remains readable.
6. Test Data and Parameterization
Q: What problem does SharedArray solve?
SharedArray loads read-only fixture data once per load generator process and exposes it efficiently to VUs. Without it, parsing a large JSON or CSV fixture in init context for every VU can multiply memory use. Its factory must run in init context, and returned values should be treated as immutable. It improves generator efficiency but does not coordinate which row a distributed instance selects.
Q: How do you assign unique data rows to VUs?
For one local instance, data[(__VU - 1) % data.length] gives a stable row per VU, while an iteration-based index rotates rows. In distributed execution, __VU may not be globally unique across every process, so use execution identifiers from k6/execution, pre-partition files, or provision data through a coordinating service. Check that available records cover peak concurrent sessions and retries. A modulo that silently reuses accounts can create locks and misleading contention.
Q: How would you load CSV data?
Parse the file inside a SharedArray factory using a supported CSV parser bundled with the test or an available k6 module. Validate headers, row counts, and required fields during initialization so malformed fixtures fail before load begins. Do not read a different file from the filesystem during each iteration because VUs cannot use Node's fs. For modest fixtures, pre-converting CSV to JSON can simplify dependencies and review.
Q: Should test data be created in setup()?
setup() is appropriate for a bounded amount of prerequisite data that can be created once and serialized to the VUs. It becomes a bottleneck when thousands of records are generated sequentially or when every VU needs exclusive mutable state. For large tests, prepare data before the timed run or use a parallel provisioning job. Keep setup traffic separate from performance measurements and make cleanup safe to retry.
Q: How do you prevent test data from biasing results?
Use a representative mix of cache hits and misses, object sizes, account histories, permissions, and search selectivity. Rotate enough records to avoid one hot object unless hot-key behavior is intentional. Verify that data preparation has created the expected database distribution before starting load. Document synthetic deviations because a perfectly uniform dataset can produce unrealistically favorable query plans.
7. Timing, Pacing, and Request Control
Q: What is the purpose of sleep()?
sleep(seconds) pauses the current VU and is commonly used to model user think time or pacing in a closed workload. It should come from observed behavior, preferably a distribution rather than the same fixed value for every user. Adding sleep to an arrival-rate scenario does not lower the configured arrival rate; it increases the VUs needed to sustain it. Never add arbitrary sleep merely to make a graph look smooth.
Q: How do you distinguish response time from iteration duration?
http_req_duration measures request time from sending through receiving the response, excluding blocked and connecting phases that have separate metrics. iteration_duration spans the whole iteration, including multiple calls, JavaScript processing, checks, and sleeps. A slow iteration with normal request latency may indicate pacing or client-side work rather than a server regression. Choose the metric whose boundary matches the requirement.
Q: What is http.batch(), and when would you use it?
http.batch() issues multiple requests concurrently from a VU, which can model resources or independent API calls a client starts in parallel. It is not a shortcut for increasing business-user concurrency, and it can create an unrealistic burst if the real client serializes calls. Apply checks to each returned response and understand per-host connection limits. Use it only when client traces show genuine overlap.
Q: How do connection reuse and noConnectionReuse affect a test?
k6 normally reuses connections, which resembles modern clients and avoids measuring a fresh handshake on every request. Disabling reuse can model special clients or diagnose connection behavior, but it increases handshake, socket, and TLS load substantially. noVUConnectionReuse and noConnectionReuse have different scopes, so configure them only after confirming the intended lifecycle. Treat connection policy as part of the workload model, not a tuning knob for desired latency.
8. Metrics, Tags, and Result Interpretation
Q: Name the four custom metric types in k6.
Counter accumulates values, Gauge retains the latest value while reporting min and max, Rate tracks the share of nonzero samples, and Trend captures a value distribution with statistics and percentiles. Choose the type based on the question: orders completed, queue depth, business failure ratio, or checkout duration. Declare metrics in init context and add samples during execution. Metric names should remain stable because dashboards and thresholds depend on them.
Q: How would you measure a business error rate?
Create a Rate, add true when the response is technically successful but the business operation failed, and threshold it explicitly. This separates domain rejection from transport failures such as timeouts or HTTP 500 responses. Tag the request or custom metric by a low-cardinality operation when separate objectives exist. Define whether expected rejections, such as an intentionally invalid coupon, count as errors before the run.
Q: Why are percentiles preferred over averages?
An average compresses the distribution and can hide a slow minority behind many fast responses. Percentiles show a boundary, for example that 95 percent of samples completed below a value, although they still do not reveal every distribution shape. Report sample count and errors with percentiles because a p95 from a tiny or heavily failed dataset is weak evidence. Tie chosen percentiles to user experience or a service objective rather than convention alone.
Q: What does dropped_iterations tell you?
It counts iterations an arrival-rate executor intended to start but could not, often because no VU was available before the schedule moved on. That can mean preAllocatedVUs or maxVUs is too low, responses became too slow, or the generator is constrained. Dropped work means achieved load differs from planned load, so result interpretation must call it out. Raising VUs blindly is unsafe until generator CPU, memory, network, and server behavior are inspected.
Q: How should tags be designed?
Use stable, low-cardinality dimensions such as endpoint name, scenario, flow, operation, or expected response class. Avoid request IDs, timestamps, customer emails, and raw URLs with unique path parameters. Normalize dynamic paths into a name tag so /orders/123 and /orders/456 aggregate as one operation. Good tags let thresholds and dashboards isolate meaningful behavior without overwhelming the metrics backend.
Q: How do you create a custom end-of-test report?
Export handleSummary(data) and return an object whose keys are output paths or stdout, with string or binary content as values. Use it for a compact JSON artifact, an HTML report generated by a maintained library, or a console summary tailored to CI. Keep raw metric exports available when deeper analysis is required because a summary cannot reconstruct every time series. Do not let report formatting change the actual pass or fail criteria.
9. Debugging and Script Reliability
Q: A script receives unexpected 401 responses under load. How do you debug it?
First tag and sample failures to determine whether they correlate with a scenario, token age, user account, or generator instance. Validate token extraction, expiration, refresh logic, audience, clock skew, and accidental credential sharing. Run one VU with bounded response logging and compare the request with a known-good client. If low load passes but sustained load fails, inspect identity-provider quotas and refresh storms rather than assuming an application latency defect.
Q: Why is unrestricted response logging dangerous in a load test?
Printing every response consumes CPU and I/O on the generator, produces enormous logs, and may expose tokens or personal data. The observer can become the bottleneck and alter the workload it is measuring. Log only a small, redacted sample of failures or use conditional counters and tags for aggregate diagnosis. Reproduce a representative failure at low load for detailed payload inspection.
Q: How do you handle an occasional malformed JSON response?
Check status and content type before parsing, then catch parse failure or inspect a bounded body excerpt without leaking sensitive content. Record a dedicated custom error metric so malformed payloads remain visible even if the server returned 200. Do not let an unhandled exception terminate the VU's iteration before useful diagnostics are recorded. The validation should reflect whether malformed JSON makes the user transaction fail.
Q: What causes context deadline exceeded or request timeouts?
The request may exceed its configured timeout because the service is slow, a connection cannot be established, DNS stalls, or the generator lacks resources. Compare k6 timing components, server traces, load balancer logs, and generator telemetry at the same timestamp. Increasing the timeout may be correct for a known long operation, but it does not repair saturation. Preserve timeout errors as failures when they violate the user contract.
Q: How do you prove the load generator is not the bottleneck?
Monitor generator CPU, memory, network throughput, open connections, DNS behavior, and dropped iterations while incrementally increasing load. Compare achieved request rate and latency across generator sizes or distributed workers. Remove excessive logging and expensive script-side parsing, then repeat a controlled run. A trustworthy report states generator headroom and the k6 version alongside server results.
10. Advanced and Scenario-Based k6 Questions
Q: How would you design a spike test?
Start from a stable baseline, increase arrival rate or concurrency sharply to an evidence-based peak, hold it long enough to observe queues, then return to baseline. Define protective abort criteria and watch recovery, autoscaling, error budgets, and backlog drain. A spike is not merely a very large number of VUs; its defining property is the rapid change in demand. Coordinate safety limits with operators before running against shared infrastructure.
Q: How would you design a soak test?
Run a representative steady workload for long enough to expose leaks, pool exhaustion, log growth, cache churn, and scheduled background interactions. Keep data supply sustainable and monitor both generator and system resources over time. Thresholds should cover correctness and latency, while trend analysis looks for degradation even when final gates pass. Include a controlled ramp-up and post-load recovery observation.
Q: How would you test an API rate limiter?
Create identities and source dimensions that match the limiter key, then send controlled traffic just below, at, and above the documented quota. Check allowed responses, expected 429 responses, headers such as retry guidance, reset behavior, and fairness between clients. Separate expected throttling from unexpected request failure in metrics. Avoid distributed generators accidentally changing the source-IP dimension unless that is part of the test.
Q: How do you test server-sent events with k6?
Use the supported streaming capability or an appropriate maintained extension for the exact protocol behavior, and model connection count, event cadence, connection lifetime, and reconnect rules. Validate event content and gaps rather than treating the initial HTTP handshake as success. Streaming tests have different generator constraints from short requests because connections remain open. The k6 server-sent events testing guide provides a focused implementation.
Q: When would browser-level k6 testing be valuable?
Browser scenarios measure user-facing behavior such as navigation timing and Web Vitals while exercising a real browser, which complements protocol-level load. Because browsers consume far more generator resources, use a small representative browser population beside larger protocol traffic rather than replacing all HTTP VUs. Correlate browser experience with backend saturation and frontend asset behavior. See the k6 browser Web Vitals tutorial for current APIs.
Q: How would you scale a k6 test beyond one machine?
First validate a single script and measure one generator's safe capacity, then partition or orchestrate load across workers with synchronized configuration and test data. Ensure arrival rates represent the aggregate target rather than being multiplied accidentally per instance. Centralize metrics with run identifiers and compare worker health. Kubernetes teams can use the k6 distributed testing operator guide to plan execution and aggregation.
11. How Interviewers Grade Your Answers
Interviewers grade the chain from requirement to evidence. A senior answer identifies the business event, chooses a workload model, writes code that preserves session and data behavior, defines correctness and performance gates, and explains how results could be invalidated. Syntax matters, but a memorized executor name without its traffic implication earns limited credit.
Use this answer structure during design questions:
- State the workload assumption and ask for missing production evidence.
- Select the executor and explain whether rate or concurrency is controlled.
- Describe correlation, identity, data volume, pacing, and protocol behavior.
- Define checks, scoped thresholds, and protective limits.
- Name generator and server telemetry required to interpret the outcome.
- Explain a small validation run before scaling and a repeatability plan afterward.
For coding prompts, produce the smallest runnable script that exposes configuration and pass criteria. Mention what you would change for distributed execution. You can rehearse timed answers in the QA interview practice workspace and use the resume upload dashboard to align examples with projects you can defend.
12. Common Mistakes
- Treating failed checks as if they automatically fail CI without a threshold.
- Choosing VUs before deciding whether production demand is concurrency-based or arrival-based.
- Claiming k6 is Node.js and importing unsupported filesystem or networking packages.
- Hard-coding tokens, captured correlation values, base URLs, or production credentials.
- Measuring only status 200 while ignoring business failures and response content.
- Using average latency as the sole performance gate.
- Applying unique IDs as metric tags and creating uncontrolled cardinality.
- Reusing too few accounts, which tests locks and hot data instead of representative behavior.
- Increasing
maxVUswithout checking generator capacity or dropped iterations. - Logging every response under load and changing generator performance.
- Reporting server latency without proving that the requested rate was achieved.
- Running a high-load test in a shared environment without approvals, limits, and cleanup.
A particularly damaging mistake is presenting a script as the performance test. The script is one component. The workload evidence, environment, data, observability, acceptance criteria, generator validation, and analysis make the result defensible.
13. Conclusion: k6 Scripting Interview Questions for Performance Testers
The best answers to k6 scripting interview questions for performance testers combine correct APIs with performance engineering judgment. Practice explaining lifecycle, executor choice, open versus closed models, checks and thresholds, correlation, fixture allocation, custom metrics, percentiles, and generator constraints without relying on vague definitions.
Run the examples, deliberately break a threshold, exhaust an arrival-rate VU pool, and inspect the resulting metrics. That hands-on evidence turns an interview answer from memorized syntax into a credible account of how you design, validate, and diagnose load tests.
Interview Questions and Answers
Explain the k6 lifecycle.
Init context defines imports, options, metrics, and reusable code for each VU runtime. `setup()` runs once and can pass serializable data to scenario functions and `teardown()`. Scenario functions repeat according to their executors, teardown runs once afterward, and `handleSummary()` can format final output.
What is the difference between checks and thresholds in k6?
Checks evaluate individual response conditions and record pass or fail samples. Thresholds evaluate aggregate metrics and determine whether the run meets acceptance criteria. I use checks for diagnostics and thresholds for automated release gates.
When would you use an arrival-rate executor?
I use it when external demand arrives independently of system response time, such as orders, messages, or API calls per second. The executor controls iteration start rate and adds VUs as iterations slow, up to its configured limit. I monitor dropped iterations to confirm the intended rate was actually attempted.
How do you correlate a dynamic value in k6?
I extract the token, ID, or cursor from the earlier response using JSON or HTML parsing, validate that it exists, and pass it to the dependent request. The value remains local to that user flow. I record a clear failure if extraction fails instead of sending a request with `undefined`.
Why use SharedArray in a k6 test?
`SharedArray` avoids parsing and storing a separate large fixture copy for every VU. Its factory executes in init context and returns read-only data for indexed access. It reduces generator memory use but does not by itself guarantee globally unique rows in distributed runs.
How would you validate a k6 load test before trusting its report?
I confirm the achieved rate or concurrency, request mix, test data, correlation, checks, and scoped thresholds with a small run. During full load I monitor generator capacity, dropped iterations, server telemetry, and response content. I also repeat a stable workload to distinguish a consistent system limit from noise.
What does dropped_iterations mean?
It means an executor could not start scheduled iterations. In an arrival-rate test, insufficient available VUs, long iterations, or generator constraints are common causes. Because delivered load differs from the plan, I investigate it before making capacity claims.
How do you create endpoint-specific thresholds?
I apply a stable tag such as `operation:search` or a normalized request `name`, then define a threshold on the corresponding submetric. This isolates the endpoint from unrelated fast traffic. I avoid high-cardinality tag values such as raw IDs.
How do you know whether to use VUs or arrival rate?
I ask whether demand is constrained by a population of active users or arrives independently from outside. VU executors model the former, while arrival-rate executors model the latter. Production traces and business forecasts should supply concurrency, rates, traffic mix, and pacing rather than guesswork.
How would you diagnose latency that rises only at high load?
I align k6 latency components and error rates with service traces, queue depth, pool utilization, database waits, and infrastructure saturation. I verify the generator still has headroom and achieved the requested workload. Then I repeat around the suspected knee with smaller increments to locate the limiting resource and recovery behavior.
Frequently Asked Questions
Is k6 JavaScript the same as Node.js?
No. k6 provides a JavaScript runtime with k6-specific modules and selected web APIs, but it is not Node.js. Packages that require Node built-ins such as `fs` or `child_process` are not directly compatible.
How many k6 questions should I prepare for a performance testing interview?
Prepare across concepts rather than targeting a fixed count. You should be able to code and explain lifecycle, at least four executors, checks, thresholds, correlation, parameterization, custom metrics, debugging, and result validity.
Do failed k6 checks fail the test?
A failed check records a failed sample but does not by itself guarantee a nonzero process exit. Add a threshold on `checks` or a more specific metric when the failure rate must gate CI.
Which k6 executor should I discuss in an interview?
Know both closed-model executors such as `constant-vus` and `ramping-vus`, and open-model executors such as `constant-arrival-rate` and `ramping-arrival-rate`. Explain the business arrival or concurrency assumption that drives the choice.
Can k6 scripts use external test data?
Yes. Load and parse fixture data during initialization, commonly through `SharedArray`, then assign records deliberately to VUs or iterations. Distributed tests need a global partitioning strategy if rows must be exclusive.
What metrics should a k6 interview answer mention?
Mention latency percentiles, request failure rate, achieved throughput, checks, iteration duration, and dropped iterations. Add endpoint or business-flow submetrics plus generator and server telemetry for a complete analysis.
How should I practice k6 coding questions?
Write small runnable scripts and predict their output before running them. Change executors, break a check, fail a threshold, correlate a value, add a custom metric, and explain why each change affects the workload or exit result.
Related Guides
- Appium 3 Interview Questions for Senior Testers (2026)
- Java Coding Interview Questions for Testers (2026)
- JavaScript Async Interview Questions for Automation Testers (2026)
- JavaScript Coding Interview Questions for Testers (2026)
- LLM Judge Interview Questions for AI Testers (2026)
- Python Coding Interview Questions for Testers (2026)