Flux is a fast, Docker-only load testing tool written in Rust.
No installation.
No dependencies.
Just Docker + YAML.
- Async or Sync load generation with Tokio
- Multi-step scenarios with variable extraction
- Multipart form-data with file upload support
- JSON + HTML reports with beautiful charts
- Real-time terminal display with progress bars
- JSONPath extraction for chaining requests
- Pure Docker usage - no local installation needed
- High performance - built with Rust for maximum throughput
docker build -t flux:latest .mkdir -p data resultsecho "Sample file content" > data/sample.txtSee the samples/ folder for examples.
docker run --rm \
-v $(pwd)/config.yaml:/app/config.yaml \
-v $(pwd)/data:/app/data \
-v $(pwd)/results:/app/results \
flux:latesttarget: "https://api.example.com/endpoint"
method: "GET"
headers:
Accept: "application/json"
concurrency: 20
duration: "30s"
mode: "async"
output:
json: "/app/results/output.json"
html: "/app/results/report.html"target: "https://api.example.com/users"
method: "POST"
headers:
Content-Type: "application/json"
body: |
{
"username": "test",
"email": "test@example.com"
}
concurrency: 10
duration: "15s"
mode: "async"
output:
json: "/app/results/output.json"
html: "/app/results/report.html"target: "https://api.example.com/upload"
method: "POST"
multipart:
- type: "file"
name: "avatar"
path: "/app/data/avatar.png"
- type: "field"
name: "username"
value: "john"
- type: "field"
name: "age"
value: "25"
concurrency: 5
duration: "10s"
mode: "async"
output:
json: "/app/results/output.json"
html: "/app/results/report.html"target: "https://api.example.com"
scenarios:
- name: "login"
method: "POST"
url: "/auth/login"
headers:
Content-Type: "application/json"
body: |
{
"username": "test",
"password": "secret"
}
extract:
token: "$.access_token"
user_id: "$.user.id"
- name: "get-profile"
method: "GET"
url: "/users/{{ user_id }}/profile"
headers:
Authorization: "Bearer {{ token }}"
depends_on: "login"
- name: "update-profile"
method: "PUT"
url: "/users/{{ user_id }}/profile"
headers:
Authorization: "Bearer {{ token }}"
Content-Type: "application/json"
body: |
{
"bio": "Updated bio"
}
depends_on: "get-profile"
concurrency: 10
duration: "30s"
mode: "async"
output:
json: "/app/results/output.json"
html: "/app/results/report.html"| Field | Type | Required | Default | Description |
|---|---|---|---|---|
target |
string | Yes* | - | Base URL for requests |
method |
string | No | GET | HTTP method (GET, POST, PUT, DELETE, etc.) |
headers |
map | No | {} | HTTP headers |
body |
string | No | - | Request body (ignored if multipart is set) |
multipart |
array | No | - | Multipart form data |
scenarios |
array | No | [] | Multi-step scenarios |
concurrency |
integer | No | 10 | Number of concurrent workers |
duration |
string | No | 30s | Test duration (e.g., "30s", "5m", "1h") |
mode |
string | No | async | Execution mode: "async" or "sync" |
output |
object | Yes | - | Output configuration |
* Required if not using scenarios with full URLs
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | "file" or "field" |
name |
string | Yes | Form field name |
path |
string | Yes (for file) | File path (must be in /app/data) |
value |
string | Yes (for field) | Field value |
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Step name |
method |
string | Yes | HTTP method |
url |
string | Yes | URL path or full URL |
headers |
map | No | HTTP headers |
body |
string | No | Request body |
multipart |
array | No | Multipart form data |
extract |
map | No | JSONPath extraction rules |
depends_on |
string | No | Name of step this depends on |
Use JSONPath syntax to extract values from JSON responses:
extract:
token: "$.access_token"
user_id: "$.user.id"
email: "$.user.email"Then use extracted variables with {{ variable_name }} syntax:
headers:
Authorization: "Bearer {{ token }}"
url: "/users/{{ user_id }}/profile"Flux collects comprehensive metrics for each request:
- Latency (min, max, mean, p50, p90, p95, p99)
- Throughput (requests per second)
- Status codes distribution
- Error rate and error messages
- Request timestamps for timeline analysis
Contains full raw data and summary statistics:
{
"summary": {
"total_requests": 12430,
"successful_requests": 12002,
"failed_requests": 428,
"throughput_rps": 414.33,
"p50_latency_ms": 84,
"p90_latency_ms": 152,
"p99_latency_ms": 231,
"error_rate": 3.44
},
"results": [...]
}Beautiful interactive report with:
- Summary statistics cards
- Latency distribution histogram
- Latency over time line chart
- Status code distribution pie chart
- Percentiles table
Uses Tokio for maximum concurrency. Recommended for most use cases.
mode: "async"
concurrency: 100Blocking workers with controlled request rate. Useful for testing rate limiting.
mode: "sync"
concurrency: 10docker run --rm \
-v ./config.yaml:/app/config.yaml \
-v ./data:/app/data \
-v ./results:/app/results \
flux:latestdocker run --rm \
-e RUST_LOG=debug \
-v ./config.yaml:/app/config.yaml \
-v ./data:/app/data \
-v ./results:/app/results \
flux:latest/app/config.yaml- Configuration file (required)/app/data- Directory for multipart files (optional)/app/results- Directory for output reports (required)
- Rust
- Docker (for containerized builds)
cargo build --release
./target/release/fluxdocker build -t flux:latest .See the samples/ directory for complete examples:
simple-get.yaml- Basic GET requestsimple-post.yaml- POST with JSON bodymultipart-upload.yaml- File upload with multipartscenario-auth.yaml- Multi-step authentication flow
flux/
βββ src/
β βββ main.rs # Entry point and orchestration
β βββ config.rs # YAML configuration parsing
β βββ client.rs # HTTP client wrapper
β βββ executor.rs # Load test execution engine
β βββ metrics.rs # Metrics collection
β βββ reporter.rs # Report generation
β βββ ui.rs # Terminal UI
β βββ templates/
β βββ report.html # HTML report template
βββ samples/
β βββ simple-get.yaml # GET example
β βββ simple-post.yaml # POST example
β βββ multipart-upload.yaml # Upload example
β βββ scenario-auth.yaml # Scenario example
β βββ sample.txt # Sample file
βββ data/ # Directory for multipart files
βββ results/ # Directory for output reports
βββ Cargo.toml # Rust dependencies
βββ Cargo.lock # Dependency lock file
βββ Dockerfile # Container image definition
βββ Makefile # Build and development commands
βββ build.sh # Build script
βββ run-example.sh # Run script
βββ config.yaml # Default configuration
βββ README.md # This file
βββ IMPLEMENTATION.md # Implementation details
βββ QUICKSTART.md # Quick start guide
For detailed implementation information, architecture, and technical decisions, see IMPLEMENTATION.md.
cargo testcargo fmt
cargo clippyContributions are welcome! Please ensure:
- Code follows Rust best practices
- All tests pass
- Documentation is updated
- Commit messages are clear
- Start small: Begin with low concurrency and short duration
- Monitor resources: Watch CPU and memory usage
- Use async mode: For maximum throughput
- Check reports: HTML reports provide visual insights
- Test locally first: Validate config before production testing
Built with β€οΈ using Rust