> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/resilience-testing/load-testing/create-a-load-test.md).

# Create a Load Test

The **Python** Load Test Engine is based on [Locust](https://locust.io/). It models user behavior as Python classes and tasks. Use Python when your team works in Python, when you want to express user journeys as code with conditional logic, or when you need a straightforward ramp-up to steady-state load. Python runs on both **Linux VM** and **Kubernetes** infrastructure, so it fits everything from a single on-premises host to scalable distributed runs.

***

### What you can do with Python <a href="#what-you-can-do-with-python" id="what-you-can-do-with-python"></a>

* **Reuse Python skills and scripts.** Write scenarios as Python classes, or upload an existing `.py` Locust script.
* **Test from a single host.** Run on a Linux VM for on-premises targets or direct network access to internal services.
* **Scale out on Kubernetes.** Run a master pod with worker pods for higher concurrency.
* **Model user behavior.** Weight tasks so frequent actions run more often than rare ones.

***

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* **Module access:** Access to the Harness Resilience Testing module.
* **Infrastructure:** A chaos infrastructure with load testing enabled, either a [Linux Chaos Infrastructure](/resilience-testing/chaos-testing/infrastructure/linux.md) or a [Kubernetes Chaos Infrastructure](/resilience-testing/chaos-testing/infrastructure/kubernetes.md) (v1.85.3 or later).
* **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.

***

### Create a load test <a href="#create-a-load-test" id="create-a-load-test"></a>

1. Navigate to **Resilience Testing** > **Load Testing**.
2. Click **+ New Load Test**.

{% hint style="info" %}
**TRY A SAMPLE TEST**

Click the arrow beside **+ New Load Test** and select **Try Locust Sample Test** to explore the flow with a pre-configured test before you build your own.
{% endhint %}

#### Configure the load test overview <a href="#configure-the-load-test-overview" id="configure-the-load-test-overview"></a>

On the **Overview** tab, enter the test metadata, then select the infrastructure where the test runs. Set **Name**, an optional **Description**, and optional **Tags**, then choose a **Target Type**.

{% tabs %}
{% tab title="Linux VM" %}
Select **Linux VM** as the target type, then select a Linux Chaos Infrastructure (with load testing enabled) from the **Load Test Infrastructure** dropdown. Set **Load Test Engine** to **Python** (Based on Locust).

The Harness chaos agent on the VM runs the Locust process locally and streams results back to Harness.

* Best for simple setups, on-premises hosts, or direct network access to internal services.
* Go to [Linux Infrastructure](/resilience-testing/chaos-testing/infrastructure/linux.md) for setup instructions.
  {% endtab %}

{% tab title="Kubernetes" %}
Select **Kubernetes** as the target type, then select a Kubernetes Chaos Infrastructure from the **Load Test Infrastructure** dropdown. Set **Load Test Engine** to **Python** (Based on Locust).

The agent in the cluster orchestrates a master pod and optional worker pods for load generation.

* Best for scalable, distributed load generation and cloud-native environments.
* Go to [Kubernetes Infrastructure](/resilience-testing/chaos-testing/infrastructure/kubernetes.md) for setup instructions.
  {% endtab %}
  {% endtabs %}

Use lowercase letters, numbers, and dashes in **Name**. Harness derives the **Id** from it.

**Select the services under test**

A **Services** section appears once you choose an infrastructure, and it is required. Select at least one onboarded service under **Resilience Testing Services**. The picker lists only the services onboarded against the infrastructure you selected.

If that 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 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 <a href="#define-the-test" id="define-the-test"></a>

On the **Test Configuration** tab, choose how you want to define the test workload. Locust supports two modes: upload a Python script, or reference a custom container image.

{% tabs %}
{% tab title="Upload Python script" %}
Upload a custom [Locust](https://locust.io/) `.py` script for advanced scenarios that require custom logic, authentication flows, or complex user behavior.

| Field           | Description                                                                                        |
| --------------- | -------------------------------------------------------------------------------------------------- |
| **Host URL**    | Base URL of the application under test. Locust prepends this to all relative paths in your script. |
| **Script file** | Drag and drop or browse to upload. `.py` files only.                                               |

```python
from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 3)

    @task
    def get_homepage(self):
        self.client.get("/")

    @task(2)
    def get_products(self):
        self.client.get("/api/products")
```

`@task(weight)` controls relative execution frequency across tasks.

<figure><img src="/files/MnNtzsTrKKCzR2QMdjCK" alt="The Test Configuration tab with Upload Python script selected, showing the Host URL and Locust Script File upload fields alongside the Load Configuration and Load Profile graph"><figcaption><p>Click to view full size</p></figcaption></figure>

*The Upload Python script mode. Provide an optional Host URL that Locust prepends to relative paths, upload your `.py` script, then set Users, Duration, Ramp Up Duration, and Worker Count in the Load Configuration.*
{% endtab %}

{% tab title="Using Custom Image" %}
Use a prebuilt container image as the load test source. This is useful when you have a custom Locust setup packaged as a Docker image. This mode is available on Kubernetes infrastructure only, since the image runs as a pod in the cluster.

| Field                   | Description                                                                                                                 |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Host URL**            | Base URL of the application under test.                                                                                     |
| **Load Test Image**     | Container image reference (for example, `my-registry/my-load-test:latest`).                                                 |
| **Entrypoint**          | Path to the Locust script inside the container (for example, `/scripts/locustfile.py`).                                     |
| **Arguments**           | Optional runtime arguments passed to the container (for example, `tags=smoke,fast;headless=true`).                          |
| **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**. |

<figure><img src="/files/3NKm4Qy5gHRNkyadZXUb" alt="The Test Configuration tab with Using Custom Image selected, showing the Host URL, Load Test Image, Entrypoint, and Arguments fields alongside the Load Configuration and Load Profile graph"><figcaption><p>Click to view full size</p></figcaption></figure>

*The Using Custom Image mode, available on Kubernetes only. Provide the Host URL, container image, entrypoint, and optional arguments, then set the load profile in the Load Configuration.*
{% endtab %}
{% endtabs %}

#### Configure the load profile <a href="#configure-the-load-profile" id="configure-the-load-profile"></a>

Configure how virtual users are ramped up and sustained during the test:

| Parameter                      | Description                                    | Constraint                             |
| ------------------------------ | ---------------------------------------------- | -------------------------------------- |
| **Users**                      | Peak concurrent virtual users.                 | Must be a positive integer.            |
| **Duration (seconds)**         | Total test runtime.                            | Must be greater than Ramp Up Duration. |
| **Ramp Up Duration (seconds)** | Time to reach peak users from zero.            | Must be less than Duration.            |
| **Worker Count**               | Number of worker processes that generate load. | Must be a positive integer.            |

Steady-state duration = `Duration - Ramp Up Duration`.

{% hint style="info" %}
**DISTRIBUTED LOAD REQUIRES KUBERNETES**

Only a Kubernetes target spreads load across workers, where each worker runs as its own pod. On a Linux VM the test runs as a single process on the host, so raising **Worker Count** does not distribute the load. Use a Kubernetes infrastructure when one host cannot generate enough traffic.
{% endhint %}

The **Load Profile** graph updates in real time as you adjust values. The **Load Profile Summary** shows a plain-English breakdown, for example: Ramp up to 100 users in 120s, maintain steady state for 480s, total duration 600s (10m 0s).

#### Set a value at run time <a href="#set-a-value-at-run-time" id="set-a-value-at-run-time"></a>

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](/resilience-testing/load-testing/run-in-a-pipeline.md) to supply these values from a pipeline.

#### Define variables <a href="#define-variables" id="define-variables"></a>

**Variables** is a drawer on the right edge of the Load Test Studio, available for both target types. A variable holds a value once and supplies it to the tool inputs, so a value such as a host name or a user 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 <a href="#tune-pods-with-advanced-options" id="tune-pods-with-advanced-options"></a>

**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, and does not appear for a Linux VM target.

| 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.

#### Save and run the test <a href="#save-and-run-the-test" id="save-and-run-the-test"></a>

1. Click **Save** to create the load test.
2. Find your test in the **Load Tests** list, which shows Type, Users, Duration, and recent executions at a glance.
3. Click the **Run** (▶) button on any test to start an execution.
4. Monitor real-time results during execution.

***

### Next steps <a href="#next-steps" id="next-steps"></a>

* Go to [Analyze load test results](/resilience-testing/load-testing/analyze-results.md) to interpret throughput, error rate, and response times.
* Go to [JavaScript](/resilience-testing/load-testing/create-a-load-test/k6.md) to run a JavaScript-based test with thresholds on Kubernetes.
* Go to [Java](/resilience-testing/load-testing/create-a-load-test/jmeter.md) to run an existing `.jmx` test plan on Kubernetes.
* Go to [Composite load tests](/resilience-testing/load-testing/composite-load-tests.md) to run this test alongside a probe that measures health while the load is applied.
* Go to [Key concepts](/resilience-testing/load-testing/get-started.md#key-concepts) to review virtual users, ramp-up, and load profiles.
