Skip to content

Latest commit

 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

goload

HTTP load-testing CLI with multi-step YAML scenarios.

A single static binary that benchmarks one endpoint or drives a full virtual-user flow — login, extract a token, fan out parallel requests — and reports it all in your terminal, JSON, and a standalone HTML page.

CI Go Reference Go Report Card Go License

$ goload run --url https://example.com/api --duration 30s --concurrency 50
reqs: 8431 | rps: 702.00 | p95: 180ms | errors: 0.14%

Contents

Why goload

Most load testers hammer a single URL. Real traffic doesn't look like that — a user logs in, gets a token, then makes several authenticated calls, some of them at once. goload models that directly.

  • Multi-step YAML scenarios — sequential steps with a parallel block for concurrent requests inside one virtual-user session.
  • Pass data between steps — extract a value from one response (json:$.path or header:Name) and template it into the next request with {{var}}.
  • Two limit modes — bound a run by total requests (-n) or wall-clock duration (-d), with optional RPS throttling.
  • Live terminal output — RPS, p95, and error rate update in place while the run is active.
  • Three report formats — terminal summary, machine-readable JSON, and a standalone HTML page with a latency chart, status-code table, and per-step breakdown.
  • One dependency-light binary — stdlib net/http under the hood, no runtime needed.

Install

go install github.com/egordushenko/goload/cmd/goload@latest

Or build from source:

git clone https://github.com/egordushenko/goload
cd goload
go build -o goload ./cmd/goload

Quick start

# Fixed number of requests at a set concurrency
goload run --url https://example.com/api --requests 5000 --concurrency 50

# Run for a duration, throttled to 200 requests/sec
goload run --url https://example.com/api --duration 30s --concurrency 100 --rps 200

# Save machine and human reports
goload run --url https://example.com/api --requests 1000 --json results.json --report report.html

Live output updates in place while the run is active:

reqs: 8431 | rps: 702.00 | p95: 180ms | errors: 0.14%

Scenarios

Scenario mode runs one virtual-user session per worker job. Steps are sequential by default; a parallel block runs its child requests concurrently inside the same session.

name: "User checkout flow"
variables:
  base_url: "https://api.example.com"
  api_key: "${API_KEY}"          # ${VAR} expands from the environment

steps:
  - name: "login"
    request:
      method: POST
      url: "{{base_url}}/auth/login"
      headers:
        Content-Type: application/json
      body: |
        {"user": "test", "pass": "test"}
    extract:
      token: "json:$.access_token"   # capture for later steps
    expect:
      status: 200

  - name: "get_profile"
    request:
      method: GET
      url: "{{base_url}}/profile"
      headers:
        Authorization: "Bearer {{token}}"   # use the captured token
    expect:
      status: 200

  - name: "parallel_widgets"
    parallel:
      - name: "widget_a"
        request: { method: GET, url: "{{base_url}}/widgets/a" }
      - name: "widget_b"
        request: { method: GET, url: "{{base_url}}/widgets/b" }

Run it:

goload run --scenario examples/checkout.yaml --duration 60s --concurrency 20 --report report.html

Extraction expressions:

Expression Reads
json:$.path a value from the JSON response body
header:Name a response header

By default a failed expect.status records an error and the virtual session continues. Use --stop-on-error to halt the current session after the first failed step.

Reports

JSON includes config, the overall summary, status-code distribution, a time-series of samples, and per-step summaries. Durations are encoded as Go duration nanoseconds.

goload run --url https://example.com --requests 100 --json results.json

HTML is a single standalone file — inline styles, embedded data, a p95-over-time chart, status-code table, and step breakdown. Nothing external to load.

goload run --url https://example.com --requests 100 --report report.html

How it compares

Feature goload hey vegeta
Single endpoint load test
Duration and request-count limits
RPS throttling limited
JSON output
HTML report plot
Multi-step YAML scenarios
Extract response data into later steps
Parallel requests inside a user flow

Flags

Flag Default Description
--url Target URL for simple mode
--scenario YAML scenario path
--method GET HTTP method for simple mode
--header, -H Repeatable request header, Name: value
--body Request body, or @file.json to read from disk
--requests, -n 0 Total jobs; 0 means unlimited until duration/cancel
--duration, -d 0 Run duration
--concurrency, -c 10 Worker count
--rps 0 Request/session jobs per second; 0 disables throttling
--timeout 30s Per-request timeout
--report HTML report path
--json JSON report path
--insecure false Skip TLS certificate verification
--stop-on-error false Stop current scenario session after a failed step

Exactly one of --url or --scenario is required. At least one of --requests or --duration is required.

Architecture

flowchart LR
  producer["producer"] --> jobs["job channel"]
  jobs --> workers["worker pool"]
  workers --> results["result channel"]
  results --> collector["collector"]
  collector --> metrics["metrics summary"]
  metrics --> reports["terminal / JSON / HTML"]
Loading

A producer feeds jobs into a channel, a pool of concurrency workers drains it, and every result flows back through a single collector goroutine — the only path that mutates metrics, so the hot path needs no locks on the aggregate. Cancellation and the --duration / RPS limits are driven by context.Context.

Scenario workers execute one virtual session at a time; each request step emits a result tagged with its StepName, so summaries carry both overall and per-step metrics.

The code is split into focused internal packages:

Package Responsibility
cli Flag parsing, validation, signal handling, terminal output
runner Producer, worker pool, result collection, cancellation
httpclient Request execution and transport setup
scenario YAML parsing, {{var}} templating, extraction, sequential/parallel execution
metrics Single-path collector, percentiles, time series
report JSON and standalone HTML rendering

Development

go test -race ./...   # run the test suite with the race detector
go vet ./...          # static checks
go build ./cmd/goload # build the binary

CI runs go vet, golangci-lint, and the race-enabled test suite, plus a build matrix across Linux, macOS, and Windows.

License

MIT © Egor Dushenko

About

HTTP load-testing CLI with multi-step YAML scenarios: sequential & parallel requests, response chaining between steps, RPS throttling, and JSON/HTML reports. Built in Go.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages