Skip to main content

Write load tests in Python. Run them at Rust speed.

Project description

LoadPilot

CI PyPI Python License: MIT Docs

Write load tests in Python. Run them at Rust speed.

LoadPilot — CheckoutFlow  [01:42]  steady: 100/100 RPS

  Requests/sec:     100.0      Total:     9,812
  Errors:             0.0%     Failed:         0

  Latency:
    p50:   12ms
    p95:   28ms
    p99:   41ms
    max:  203ms

  [████████████████████] 100%

LoadPilot is a load testing tool for teams that want to write scenarios in Python without the throughput ceiling of a pure-Python engine.

Scenarios are plain Python classes. HTTP execution runs in async Rust.


Install

pip install loadpilot

No Rust required — the coordinator binary is bundled in the wheel.

Supported platforms: Linux x86_64 · macOS Intel · macOS Apple Silicon · Windows x86_64


Quick Start

# scaffold a project
loadpilot init my-load-tests
cd my-load-tests

# run a scenario
loadpilot run scenarios/example.py --target https://your-api.example.com

Or run without arguments to pick a scenario interactively:

loadpilot run --target https://your-api.example.com

Getting Started in 5 minutes


Write a Scenario

from loadpilot import VUser, scenario, task, LoadClient

@scenario(rps=100, duration="2m", ramp_up="30s")
class CheckoutFlow(VUser):

    def on_start(self, client: LoadClient):
        resp = client.post("/auth/login", json={"user": "test", "pass": "secret"})
        self.token = resp.json()["access_token"]

    @task(weight=5)
    def browse(self, client: LoadClient):
        client.get("/api/products", headers={"Authorization": f"Bearer {self.token}"})

    def check_browse(self, status_code: int, body) -> None:
        assert status_code == 200
        assert isinstance(body, list)

    @task(weight=1)
    def purchase(self, client: LoadClient):
        client.post("/api/orders", json={"product_id": 42, "qty": 1},
                    headers={"Authorization": f"Bearer {self.token}"})
  • on_start — runs once per virtual user before tasks start (login, setup)
  • @task — weighted HTTP task; multiple tasks run in proportion
  • check_{task} — assertion after each request; fail = error counted

Features

Python DSL @scenario, @task, on_start, check_* — no new syntax to learn
Load profiles ramp (default), constant, step, spike
SLA thresholds fail CI with exit code 1 on p99/p95/error-rate breach
Distributed mode coordinator + N agents over NATS; local or remote, free
HTML report self-contained, open in any browser, no server required
Prometheus metrics live Grafana dashboards while the test runs
Interactive TUI loadpilot run with no args opens a scenario browser
pip install coordinator binary bundled in the wheel, no Rust needed

Performance

LoadPilot is benchmarked against k6 and Locust against a Rust/axum echo server in Docker. LoadPilot runs in PyO3 mode — with on_start (login) and check_* (assertion per task) — a realistic workload with Python callbacks active.

Precision — 500 RPS target

Tool RPS actual p50 p99 Errors CPU avg
LoadPilot (PyO3) 478 4ms 15ms 0% 14%
k6 491 8ms 118ms 0% 129%
Locust 498 150ms 1500ms 0% 88%

LoadPilot uses 9× less CPU than k6 at the same load. Locust reaches the RPS target but its Python/GIL scheduler adds significant latency (p99 ≥ 1500ms at only 500 RPS).

Max throughput — 30s, no cap

Tool RPS p50 p99 Errors CPU avg
LoadPilot (PyO3) 2205 11ms 38ms 0% 165%
k6 1799 14ms 175ms 0% 212%
Locust 677 100ms 170ms 0% 117%

1.2× k6 and 3.3× Locust at max throughput. 1.6× better CPU efficiency per request vs k6.

Full benchmark details and methodology


SLA Thresholds

@scenario(
    rps=100, duration="2m",
    thresholds={"p99_ms": 500, "p95_ms": 300, "error_rate": 1.0},
)
class CheckoutFlow(VUser): ...
Thresholds
  ✓  p99 latency       41ms  <  500ms
  ✓  p95 latency       28ms  <  300ms
  ✓  error rate         0%   <    1%

All thresholds passed.

Exit code 1 on breach — drop into any CI pipeline. Override without editing the file:

loadpilot run scenarios/checkout.py --target https://staging.example.com \
  --threshold p99_ms=800 --threshold error_rate=2

Distributed Mode

# 4 local processes
loadpilot run scenarios/checkout.py --target https://api.example.com --agents 4

# external agents on remote machines
loadpilot run scenarios/checkout.py \
  --target https://api.example.com \
  --external-agents 4

The CLI output is identical to single-machine mode — the coordinator aggregates everything transparently. on_start (login, setup) runs on the coordinator and ships per-user auth headers to agents, so distributed tests can authenticate without Python running on each agent.

Distributed mode guide


Live Monitoring

# scaffolded by `loadpilot init`
docker compose -f monitoring/docker-compose.yml up -d
# Grafana → http://localhost:3000   (LoadPilot dashboard auto-imported)
# Prometheus → http://localhost:9091

Use Grafana to correlate load test metrics with your service's own metrics (CPU, DB latency, error rates) on the same timeline.


Development

Requires just.

just test        # run all tests (Python + Rust)
just test-py     # Python tests only
just test-rust   # Rust tests only
just fix         # auto-fix lint + format
just check       # lint + format check (no writes, same as CI)
just build       # cargo build (debug)
just build-release  # cargo build --release

Documentation


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loadpilot-0.2.0.tar.gz (90.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

loadpilot-0.2.0-cp312-cp312-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.12Windows x86-64

loadpilot-0.2.0-cp312-cp312-manylinux_2_38_x86_64.whl (4.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.38+ x86-64

loadpilot-0.2.0-cp312-cp312-macosx_11_0_arm64.whl (4.3 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

File details

Details for the file loadpilot-0.2.0.tar.gz.

File metadata

  • Download URL: loadpilot-0.2.0.tar.gz
  • Upload date:
  • Size: 90.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for loadpilot-0.2.0.tar.gz
Algorithm Hash digest
SHA256 457189a8e25ed1d3819c742dd2e91475585309f7301871eb31465bc147b6c577
MD5 6f05b0dca97932bf5cdcb5edd46c8e25
BLAKE2b-256 e9b98164be0da370b1943dcf1dd8feb50aa5c608bb3043ca09f47803ff8831b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for loadpilot-0.2.0.tar.gz:

Publisher: release.yml on VladislavAkulich/loadpilot

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file loadpilot-0.2.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: loadpilot-0.2.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for loadpilot-0.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 f9bc3ce4837176ced4f52bb2066f013066b166731879c571be0053818628b7e2
MD5 03c04aeaf9ecc78deefef60af649aa5b
BLAKE2b-256 7c0bebe145358be681129e19760f24069c2f0c472620dfb49d5157931e486a6c

See more details on using hashes here.

Provenance

The following attestation bundles were made for loadpilot-0.2.0-cp312-cp312-win_amd64.whl:

Publisher: release.yml on VladislavAkulich/loadpilot

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file loadpilot-0.2.0-cp312-cp312-manylinux_2_38_x86_64.whl.

File metadata

File hashes

Hashes for loadpilot-0.2.0-cp312-cp312-manylinux_2_38_x86_64.whl
Algorithm Hash digest
SHA256 f1fb20bcd2e39aa708b9db858a44f3756332225ddde8f12f8c5fca9d0706bb20
MD5 2320f9004cd9e967c6742eb3e8aa8b7a
BLAKE2b-256 57136880aaa094dc87c1255b75ba768f464120909bfb0f97404397e0a13861d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for loadpilot-0.2.0-cp312-cp312-manylinux_2_38_x86_64.whl:

Publisher: release.yml on VladislavAkulich/loadpilot

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file loadpilot-0.2.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for loadpilot-0.2.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 34fa37e5cbc6441f1e26ef590da874950d80da840ebe997272390c3ea30309b3
MD5 7293b31b85cfbaf0ee6c2bd9674471dd
BLAKE2b-256 2f45210700f85b0d5abaf88a43cca752825a652a59162c9581c36ca8baba4a92

See more details on using hashes here.

Provenance

The following attestation bundles were made for loadpilot-0.2.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on VladislavAkulich/loadpilot

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page