# tsenart/vegeta: HTTP load testing at a fixed request rate

> Vegeta is a Go CLI and library that fires HTTP requests at a constant rate, records the results in a binary format, and reports latency distributions. It is MIT licensed and the last push was on 2026-09-24.

**tsenart/vegeta** — HTTP load testing tool and library. It's over 9000!

- Repository: https://github.com/tsenart/vegeta
- Website: http://godoc.org/github.com/tsenart/vegeta/lib
- Stars: 25,201 · Forks: 1,422
- Language: Go
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/tsenart-vegeta

## The constant-rate gap Vegeta fills

Most quick load tests are loops. You write a script that fires N requests as fast as the client can manage, then you look at the average. That number tells you how fast your laptop and the network can push, not how the service behaves at a rate you chose. Vegeta is built around the opposite assumption: you pick a request rate, and the tool tries to hold it. The README describes the project as "built out of a need to drill HTTP services with a constant request rate", and the default is 50 requests per second.

The audience is narrow and specific. If you are a backend engineer who wants a repeatable number to compare before and after a deploy, or a Go developer who wants to call the same machinery from a test, Vegeta fits. If you want a browser-driven scenario with login, cart and checkout steps, it does not. Targets are HTTP requests, not user journeys.

## How the attack loop and the binary result file fit together

The pipeline has four commands and one intermediate format. The attack command reads targets, sends requests, and writes a binary stream of results. The report command reads that stream and produces text, JSON, histograms or an HDR plot. The encode command converts the stream to csv, gob or json. The plot command turns it into an HTML page.

The rate flag is the core control. It takes a value like 50/1s, and the documentation notes that 0 means infinity. Workers start at 10 and can grow to -max-workers. The tool avoids what the README calls coordinated omission, which is the distortion you get when a generator stalls and then reports only the fast responses it managed to collect. The README links to a pull request comment and an article on the subject rather than explaining the fix in detail, so the mechanism is a claim you should verify against your own results.

Because results are a file, you can attack once and report many ways. The same results.bin feeds a text summary, a JSON metrics file and a histogram without re-running the test. That is the design decision that makes the tool composable, and it is also why the binary format exists instead of plain text.

## Installing Vegeta and running a first attack

The README lists pre-compiled executables on the GitHub releases page, Homebrew and MacPorts on macOS, pacman on Arch Linux, and pkg on FreeBSD. On macOS, Homebrew is the shortest path:

```shell
$ brew update && brew install vegeta
```

After that, vegeta -version should print a version and exit. On Arch Linux the equivalent is pacman -S vegeta, and on FreeBSD it is pkg install vegeta. If you prefer to build from source, the README gives this sequence, which requires a Go toolchain because the Makefile runs go build:

```shell
git clone https://github.com/tsenart/vegeta
cd vegeta
make vegeta
mv vegeta ~/bin # Or elsewhere, up to you.
```

The Makefile builds with CGO_ENABLED=0 and -tags=netgo, so the resulting binary is static. The repository also contains a Dockerfile, which builds the binary in a golang:1.20-alpine3.18 stage and copies it into alpine:3.18.0 with vegeta as the entrypoint.

A first real use is a five second attack against a local service, with the targets coming from stdin in the plain HTTP format. This is the README's own example:

```bash
echo "GET http://localhost/" | vegeta attack -duration=5s | tee results.bin | vegeta report
```

The report command defaults to text output. You should see a summary with latency percentiles and a success ratio. To keep the numbers instead of the prose, the README shows this form:

```bash
vegeta report -type=json results.bin > metrics.json
```

For a latency distribution rather than percentiles, the report command accepts a histogram type with explicit buckets:

```bash
cat results.bin | vegeta report -type="hist[0,100ms,200ms,300ms]"
```

One flag worth knowing before you point this at anything shared: -rate defaults to 50/1s, so a five second run sends roughly 250 requests. Raise -duration or -rate deliberately, and use -max-body if you do not want response bodies captured in the result file.

## Where the constant-rate model breaks down

Vegeta does not maintain sessions in the browser sense. Each target is an HTTP request, and the -body flag sets one body file for every request unless a target overrides it. If your service behaves differently for a logged-in user with a cookie jar and a sequence of dependent calls, you are testing a shape of traffic that Vegeta does not generate. You can add headers per request and you can vary targets, but ordering and state are your problem.

The DNS behaviour is another boundary. The -dns-ttl flag caches lookups, with -1 disabling the cache and 0 meaning forever, and -resolvers replaces the system resolver entirely. That is useful for testing a specific address, but it also means a misconfigured resolver silently changes what you are measuring. The -connect-to flag goes further and maps a host and port to a different host and port, which is convenient for pointing a production hostname at staging. Both flags make it easy to attack something other than what you think you are attacking, so read the target file before you run.

The result file is binary and the format is not documented in the README. The encode command exists to convert it, and the report command reads it, but if you want to process results in another language you are going through csv or json. That is a real constraint on tooling, not a detail.

## Vegeta as a Go library versus hey or k6

The README states that Vegeta is usable both as a command line tool and as a Go library, with the library documented at pkg.go.dev under the v12 module path. That dual identity is the clearest difference from the alternatives.

hey is a Go load generator with a similar command line shape, but it is aimed at a quick request-count run rather than a rate-controlled attack with a persisted result format. If you want one command and a summary, hey is less ceremony. If you want to keep the raw results and report on them later, Vegeta's file-based pipeline is the point.

k6 takes a different approach again: test scenarios are written in JavaScript, which makes staged ramps and per-user logic expressible, at the cost of a scripting runtime and its own execution model. Vegeta's targets are declarative lines, and the tool has no scripting layer. That is a smaller surface to learn and a smaller surface to express yourself in.

The versioning scheme is worth noting for library users. Since v8.0.0 the CLI and library are versioned separately, with CLI releases tagged cli/vMAJOR.MINOR.PATCH and library releases tagged both lib/vMAJOR.MINOR.PATCH and vMAJOR.MINOR.PATCH, the latter for go mod compatibility. The current module path in go.mod is github.com/tsenart/vegeta/v12 and it declares go 1.22.

## Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-24. The most recent release listed is v12.13.0 on 2025-10-31, after v12.12.0 on 2024-07-29 and v12.11.3 on 2024-07-27. The gap between v12.12.0 and v12.13.0 is roughly fifteen months, so releases are not frequent. The README states that both the library and the CLI follow SemVer v2.0.0, and the separate tagging scheme for cli/ and lib/ means an upgrade can move one component without the other. Upgrading the library means changing the module path only when the major version changes; the current path pins v12.

The licence is MIT. That permits use, modification and redistribution with the licence text preserved, and it comes with no warranty. This is a summary of the identifier, not legal advice; read the LICENSE file in the repository before you rely on it for a commercial deployment. The README also lists a Gitter channel and a Bitcoin donation badge, which are the project's stated support channels.

## Conclusion

Adopt Vegeta if you want a constant-rate generator you can script and pipe, and if you are willing to read its report output rather than a dashboard. Do not adopt it if you need scripted user journeys with think times; it replays targets, not sessions. Before committing, confirm the target file format and the -rate value you intend to use against a staging host, and check whether -prometheus-addr fits your monitoring setup.

## FAQ

### How do I install Vegeta?

The README lists pre-compiled executables on the GitHub releases page, Homebrew and MacPorts on macOS, pacman on Arch Linux, and pkg on FreeBSD. Building from source uses git clone, make vegeta, and then moving the binary somewhere on your PATH.

### What alternatives to Vegeta should I consider?

hey is a similar Go load generator aimed at a quick request-count run, and k6 lets you write scenarios in JavaScript instead of declarative target lines. The main practical difference is that Vegeta keeps results in a binary file you can report on repeatedly with the report, encode and plot commands.

### Does Vegeta send requests at a fixed rate?

Yes. The attack command has a -rate flag that defaults to 50/1s, and the README says a value of 0 means infinity. The project describes itself as built out of a need to drill HTTP services with a constant request rate.

### Can I use Vegeta as a Go library instead of the CLI?

The README states that Vegeta is usable as both a command line tool and a Go library, and links to the library documentation at pkg.go.dev. The go.mod module path is github.com/tsenart/vegeta/v12 and it declares go 1.22.

### What is the result file format produced by vegeta attack?

The attack command writes a binary stream, which the README's examples pipe into vegeta report or vegeta plot. The encode command can convert that stream to csv, gob or json if you need to process it elsewhere.

## Sources

- [License: MIT](https://github.com/tsenart/vegeta/blob/master/LICENSE)
- [Project website](http://godoc.org/github.com/tsenart/vegeta/lib)
- [README](https://github.com/tsenart/vegeta/blob/master/README.md)
- [Releases](https://github.com/tsenart/vegeta/releases)
- [tsenart/vegeta on GitHub](https://github.com/tsenart/vegeta)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/tsenart-vegeta
