Skip to main content

Async distributed load-testing framework contracts and runtime

Project description

vikhry

vikhry is an async distributed load-testing framework built for high concurrency, horizontal scaling, and workloads that need globally unique resources.

It combines:

  • a Python runtime for writing virtual-user scenarios;
  • an orchestrator that manages test lifecycle and aggregates metrics;
  • worker processes that execute VUs;
  • Redis as the shared coordination layer;
  • a built-in web UI served by the orchestrator.

Architecture

At a high level, vikhry has four runtime parts:

  1. orchestrator Handles the test state machine, exposes HTTP/WebSocket APIs, serves the UI, and coordinates workers.
  2. worker Runs VU tasks, processes orchestrator commands, publishes metrics, and manages acquired resources.
  3. redis Stores shared state, worker presence, user assignments, resources, and metric streams.
  4. ui A React frontend bundled into the Python package and served by the orchestrator.

Lifecycle flow:

IDLE -> PREPARING -> RUNNING -> STOPPING -> IDLE

Install and run

Install from PyPI:

pip install vikhry

Start local infrastructure:

vikhry infra up --worker-count 3 --scenario my_scenario:DemoVU

This command:

  • checks that Docker is available;
  • starts Redis in a Docker container;
  • starts the orchestrator;
  • starts the requested number of workers.

Open:

  • UI: http://127.0.0.1:8080/
  • API: http://127.0.0.1:8080

Stop everything:

vikhry infra down

Example test file

Create my_scenario.py:

from __future__ import annotations

from typing import Any

from vikhry import ReqwestClient, VU, between, resource, step


@resource(name="users")
async def create_user(resource_id: int | str, _ctx: object) -> dict[str, Any]:
    rid = str(resource_id)
    return {
        "resource_id": rid,
        "username": f"user_{rid}",
        "password": "password",
    }


class DemoVU(VU):
    http = ReqwestClient(timeout=5.0)

    async def on_init(self, base_url: str) -> None:
        self.http = self.http(base_url=base_url)

    async def on_start(self) -> None:
        self.user = await self.resources.acquire("users")

    async def on_stop(self) -> None:
        await self.resources.release("users", str(self.user["resource_id"]))

    @step(name="login", weight=1.0, every_s=between(10.0, 15.0), timeout=5.0)
    async def login(self) -> None:
        response = await self.http.post(
            "/auth",
            json={
                "username": self.user["username"],
                "password": self.user["password"],
            },
        )
        if response.status >= 400:
            raise RuntimeError(f"login returned HTTP {response.status}")

    @step(name="catalog", weight=3.0, requires=("login",), every_s=between(0.2, 1.0))
    async def catalog(self) -> None:
        response = await self.http.get("/catalog")
        if response.status >= 400:
            raise RuntimeError(f"catalog returned HTTP {response.status}")

Run it:

vikhry infra up --worker-count 3 --scenario my_scenario:DemoVU

Test authoring capabilities

vikhry scenarios are plain Python classes built on top of the VU DSL.

What you can define:

  • VU.on_init(...) Accept runtime parameters for each VU instance.
  • VU.on_start() / VU.on_stop() Allocate and release state or resources around the VU lifecycle.
  • @step(...) Define executable load steps.
  • @resource(name="...") Define global resource factories managed through Redis-backed pools.
  • ReqwestClient Use an async HTTP client for relative or absolute requests.
  • emit_metric(...) and @metric(...) Publish custom metrics in addition to automatic HTTP and step metrics.

Step controls:

  • weight Weighted random scheduling between eligible steps.
  • requires Declare prerequisites by step name.
  • every_s Throttle step execution to a fixed or randomized interval.
  • timeout Fail a step if it exceeds its maximum runtime.

Resource model:

  • resource factories create globally tracked objects;
  • workers acquire resources with self.resources.acquire(name);
  • workers release them with self.resources.release(name, resource_id).

Packaging and release

The Python package includes the built UI assets.

Build locally:

./scripts/build_frontend.sh
uv build

Release automation:

  • .github/workflows/release-artifacts.yml Builds the frontend, creates wheel and sdist, and publishes the package to PyPI using PYPI_TOKEN.
  • .github/workflows/docker-image.yml Builds and publishes the runtime Docker image to ghcr.io/<owner>/<repo> on every branch push.

The package version is taken from project.version in pyproject.toml.

Documentation site

The public documentation site is built with Starlight from the files under docs.

Run it locally:

cd docs
npm install
npm run dev

Build static output:

cd docs
npm run build

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

vikhry-0.2.8.tar.gz (437.5 kB view details)

Uploaded Source

Built Distribution

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

vikhry-0.2.8-py3-none-any.whl (265.0 kB view details)

Uploaded Python 3

File details

Details for the file vikhry-0.2.8.tar.gz.

File metadata

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

File hashes

Hashes for vikhry-0.2.8.tar.gz
Algorithm Hash digest
SHA256 78ff8857860af187d5ab57db959cba1ce64ff9a962ec8a56525255632458537b
MD5 f0b482324fdf50e09bba62ad4653eeb0
BLAKE2b-256 1b39639fa89ae359ef18766ff9dda4c1b14dc54f259e6b30daa226fe310b268c

See more details on using hashes here.

Provenance

The following attestation bundles were made for vikhry-0.2.8.tar.gz:

Publisher: release-artifacts.yml on gigimon/vikhry

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

File details

Details for the file vikhry-0.2.8-py3-none-any.whl.

File metadata

  • Download URL: vikhry-0.2.8-py3-none-any.whl
  • Upload date:
  • Size: 265.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for vikhry-0.2.8-py3-none-any.whl
Algorithm Hash digest
SHA256 a7c58ab59cf439c2b21b5f4e598d93f14bb2c518c99f65a9d8a6ae26b747d14b
MD5 5ee7f1e6c77fdbb5f6427ec82b07de14
BLAKE2b-256 184c678496895a019c7d72d4e4cd53dce75a7636296f9bb004fdbacf615008e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for vikhry-0.2.8-py3-none-any.whl:

Publisher: release-artifacts.yml on gigimon/vikhry

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