JavaScript
The JavaScript Load Test Engine is based on k6. Use it when you want a test that does more than generate traffic: it scripts realistic user flows, enforces pass/fail criteria, and runs the same way locally and in continuous integration. In Harness Resilience Testing, you build a JavaScript test in the Load Test Studio and run it on your Kubernetes infrastructure.
JavaScript load tests run on Kubernetes infrastructure. To run on a Linux VM, use Python.
What you can do with JavaScript
Each goal below maps to a k6 capability you configure on this page:
- Gate a release on performance. Declare a threshold such as "95th-percentile latency under 5000 ms" so a regression fails the run automatically.
- Reproduce a traffic surge. Write a stage sequence that ramps from zero to a high peak and back, mimicking a sale or launch.
- Find the breaking point. Push past expected load in stages until the system degrades.
- Catch slow leaks. Hold steady load for hours to surface memory leaks or resource exhaustion.
- Model real journeys. Run several scenarios in parallel, such as a browse flow and a checkout flow, each with its own schedule.
- Drive very high load. Use distributed execution to split a test across runner pods for high concurrency.
Prerequisites
- Module access: Access to the Harness Resilience Testing module.
- Kubernetes infrastructure: A Kubernetes Chaos Infrastructure (v1.85.3 or later) with load testing enabled. Load testing is enabled by default on Kubernetes infrastructure.
- Environment: An environment created in your project for the infrastructure.
- An onboarded service: At least one service onboarded against that infrastructure.
- Reachable target: Target application endpoints accessible from the test infrastructure.
- A k6 script: A
.jsfile, or a container image that carries one. Harness runs the script you supply and does not generate one for you.
Create a load test
- Navigate to Resilience Testing > Load Testing.
- Click + New Load Test.
Click the arrow beside + New Load Test and select Try K6 Sample Test to explore the flow with a pre-configured test before you build your own.
Configure the load test overview
On the Overview tab, enter the test metadata and select where the test runs:
| Field | Description |
|---|---|
| Name | A descriptive identifier for the test. Use lowercase letters, numbers, and dashes only. Harness derives the Id from it. |
| Description | (Optional) What the test validates. |
| Tags | (Optional) Labels to organize tests. |
| Target Type | Select Kubernetes. The agent in the cluster runs k6 as a master pod and optional runner pods. |
| Load Test Infrastructure | Select a Kubernetes Chaos Infrastructure from the dropdown. |
| Resilience Testing Services | Select at least one onboarded service the test targets. This section appears once the infrastructure is set. |
| Load Test Engine | Select JavaScript (Based on K6). |
Select the services under test
The Services section appears after you choose an infrastructure, and it is required. The picker lists only the services onboarded against that infrastructure, so a test cannot reference a workload the infrastructure does not manage.
If the infrastructure has no onboarded services, the section reads No resilience testing services yet and offers Onboard a Service. You cannot continue until at least one service exists, because Harness reports load results against the service rather than against the test alone.
Click Next to proceed to Test Configuration.
Define the test
On the Test Configuration tab, choose how you want to supply the k6 script. You write the workload in JavaScript, and Harness runs the script exactly as you provide it.
- Upload K6 script
- Using Custom Image
Upload a custom k6 JavaScript file when you need full control over user behavior, custom logic, or advanced k6 features. The script must export a default function: export default function () { ... }.
| Field | Description |
|---|---|
| Host URL | Passed to your script as __ENV.HOST_URL. Leave blank if your script uses hardcoded URLs. |
| k6 Script File | Drag and drop or browse to upload a .js file. Available globals are __ENV.HOST_URL and any variables you declare. |
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 50 },
{ duration: '5m', target: 50 },
{ duration: '1m', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<5000'],
},
};
export default function () {
const res = http.get(`${__ENV.HOST_URL}/api/products`);
check(res, { 'status is 200': (r) => r.status === 200 });
sleep(1);
}
When your script declares its own scenarios, stages, or thresholds, k6 runs them as written. The Load Profile Overrides below apply only when the script does not define its own scenarios.
Use a prebuilt container image as the load test source. The image must contain the k6 binary and your script. This is useful when you maintain a packaged k6 setup outside Harness.
| Field | Description |
|---|---|
| Host URL | Passed to your script as __ENV.HOST_URL. Leave blank if your script uses hardcoded URLs. |
| Load Test Image | Container image reference (for example, my-registry/my-load-test:latest). |
| Entrypoint | Path to the .js script inside the image, passed as the positional argument to k6 run (for example, /scripts/script.js). |
| Load args | Additional CLI flags appended to the k6 run command (for example, --quiet, --out=json=/tmp/r.json). |
| Image Registry Type | Select Public for an image anyone can pull, or Private to pull with credentials. |
| Secret Name | The Kubernetes image pull secret used to authenticate. This field appears only when Image Registry Type is Private. |
The Load Profile Overrides always take precedence over the image. If your script defines its own scenarios or stages, set Duration to their total run time so the complete test runs.
Shape the load
How virtual users (VUs) are scheduled over time comes from your script. Declare scenarios or stages in options, and k6 runs them as written.
export const options = {
scenarios: {
browse: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 500 },
{ duration: '1m', target: 0 },
],
},
},
};
The ramping-vus executor ramps VUs linearly to each target and is the most common choice for gradual load. Add a second entry under scenarios to run workloads in parallel, such as a browse flow alongside a checkout flow. Go to the k6 executors reference to review the other executors.
Override the profile
Load Profile Overrides is a small set of fields on the Test Configuration tab for tests whose script does not declare its own schedule. The overrides apply only to k6's implicit default scenario, and k6 ignores them once your script declares scenarios or stages.
| Override | Description |
|---|---|
| Users | Concurrent virtual users to run. |
| Duration (seconds) | Total run time. For scripted scenarios or stages, enter their combined duration. |
| Iterations (cap) | Maximum iterations. Leave blank to use the value from the script. |
| RPS Limit | A global cap on requests per second that always applies. It is split evenly across replicas. |
Once you upload a script and set Users and Duration, the panel beside these fields previews the resulting steady-state profile.
Gate a release with pass/fail thresholds
Thresholds turn a load test into a gate. If any threshold fails, the run is marked Failed, which makes k6 well suited to release gates in continuous integration.
k6 thresholds are declared in the script under options.thresholds, not in the Load Test Studio. Each entry names a metric and the condition it must satisfy.
export const options = {
thresholds: {
http_req_duration: ['p(95)<5000'],
http_req_failed: ['rate<0.01'],
},
};
The example fails the run if the 95th-percentile request duration reaches 5000 ms, or if more than one percent of requests fail. Harness reports the outcome of each threshold in a Thresholds table on the run detail page. A run that declares no thresholds shows no such table.
To abort as soon as a threshold is breached rather than finishing the test, add abortOnFail using the k6 threshold options.
Add environment variables
Use the Environment Variables section to pass configuration and secrets into your test without hardcoding them. Reference them inside the script as __ENV.NAME. Secrets are encrypted at rest.
Scale with distributed execution
When a single pod cannot generate enough load, distributed execution runs k6 across multiple runner pods on Kubernetes. Each replica runs a slice of the load through k6's --execution-segment flag, so the total VUs and RPS are split evenly across pods.
| Replicas | Behavior |
|---|---|
| 0 or 1 | Single-pod mode. All VUs run on one pod. |
| 2 or more | The load is split across pods. Use this for more than 1,000 VUs or sustained high requests per second. |
Set a value at run time
Every tool input carries a pin control at the end of the field. Select it to switch the field between Fixed value and Runtime input.
A fixed value is stored with the test and used on every run. A runtime input leaves the field unset, so the value is supplied when the test runs, which lets one load test serve several environments or load levels. Go to Run a load test in a pipeline to supply these values from a pipeline.
Define variables
Variables is a drawer on the right edge of the Load Test Studio. A variable holds a value once and supplies it to the tool inputs, so a value such as a host name or a thread count lives in one place instead of being repeated across fields.
Select + Add Variable and complete the New Variable dialog:
| Field | Description |
|---|---|
| Type | String, Number, or Secret. Use Secret for credentials so the value is not stored in the test definition. |
| Name | The variable name. |
| Value | The value to use. This field carries its own pin control, so a variable can itself be a runtime input. |
| Description | (Optional) What the variable is for. |
Select Save to add the row, then Apply Changes to keep the drawer's edits. The drawer lists each variable with its Variable, Description, and Value.
Tune pods with Advanced Options
Advanced Options is a drawer on the right edge of the Load Test Studio that controls how the load pods themselves behave. It applies to Kubernetes targets only, since both settings act on pods.
| Setting | Default | What it does |
|---|---|---|
| Clean-up Load Resources | On | Deletes the pods, configmaps, and secrets a run created once the run finishes. Turn it off to keep those resources for debugging, and remove them yourself afterwards. |
| Resource Requirements | Off | Sets CPU and memory requests and limits on the load pods. Turn it on when a run is throttled or evicted, or when your cluster enforces quotas. |
Select Apply Changes to keep your edits, or Discard to close the drawer without saving.
If a run fails and the logs do not explain why, turn off Clean-up Load Resources and run it again. The pods stay in the cluster so you can inspect them with kubectl describe and kubectl logs.
Save and run the test
- Click Save to create the load test.
- Find your test in the Load Tests list, which shows Type, Users, Duration, and recent executions at a glance.
- Click the Run (▶) button to start an execution.
- Monitor real-time results during execution. A breached threshold marks the run as Failed.
Next steps
- Go to Analyze load test results to interpret throughput, error rate, response times, and threshold outcomes.
- Go to Python to run a Python-based load test on Linux VM or Kubernetes.
- Go to Java to run an existing
.jmxtest plan on Kubernetes. - Go to Composite load tests to run this test alongside a probe that measures health while the load is applied.
- Go to Key concepts to review virtual users, load profiles, and thresholds.