Modern HTTP Benchmarking Tools ready for 2026 - h2load, hey & wrk

Modern HTTP Benchmarking Tools ready for 2026 - h2load, hey & wrk

The HTTP protocol continues to be the most popular communications protocol on the web. In addition to the classic web browsing with hypertext documents, HTTP is also the de-facto protocol for API communications with RESTful APIs. WebSockets and other protocols exist, but HTTP is everywhere.

The HTTP protocol itself received a significant upgrade in 2015 with the release of HTTP/2, and a second one in 2022 when HTTP/3 was published as RFC 9114, moving the transport off TCP and onto QUIC over UDP. Both are mainstream today: as of July 2026 W3Techs measures HTTP/3 on 40 percent of sites and HTTP/2 on a further 35 percent, so roughly three quarters of the web has moved past HTTP/1.1. Thanks to the improved infrastructure, free certificates from Let's Encrypt and browser vendors pushing encrypted traffic the web is faster and more secure today.

The transport layer of the web has received significant, but quiet, upgrades over the years. Perhaps because the changes have been taken on gradually, some areas have not been discussed much. One of these is HTTP benchmarking tools, which are used to generate load to a HTTP server.

Benchmarking HTTP in 2026

From the days of yore developers have used tools like Apache Bench or Siege to generate simple high concurrency traffic for benchmarks. But by todays standards these are very old; Apache Bench for example is based on the Zeus Technology tool from 1996 - that's thirty years of history. Both still ship in every distro, and both still speak HTTP/1.1 only.

With the performance requirements of contemporary web services, and runtimes like Node.js, Deno, Go and Rust that enable high HTTP throughput, the load generator deserves some care too. If your benchmarking tool saturates before your server does, you are measuring the wrong process. So developers should no longer default to Apache Bench or Siege.

This article originally covered three contemporary command line tools. Nearly a decade on, it is worth revisiting how they held up, and what has appeared since. The three original options, in alphabetical order:

  • h2load
  • hey
  • wrk

h2load

h2load is a benchmarking tool for HTTP/2 and HTTP/1.1. It is written in C and is using the nghttp2 library underneath. It has aged the best of the three. Installation is no longer a problem: it ships in the nghttp2-client package on Debian and Ubuntu, in nghttp2 on Fedora and Homebrew. The nghttp2 project remains actively maintained.

It has also gained HTTP/3. A build configured with --enable-http3 against ngtcp2 and nghttp3 will benchmark QUIC endpoints and report QUIC specific statistics such as smoothed RTT and packets lost. That build is still a compile-from-source exercise, but it makes h2load the obvious choice for anyone testing an HTTP/3 origin.

An example command to make 100000 requests to a server at a concurrency of 100 with h2load:

$ h2load -n100000 -c100 https://localhost:3000/

hey

hey is a HTTP benchmarking tool written in Go. It supports both HTTP/1.1 and HTTP/2 through the native Go libraries, with HTTP/2 behind the -h2 flag. As a standard Go application, installation is straightforward once you have the toolchain, and Homebrew carries it.

hey went quiet for a long stretch. Between v0.1.4 in 2020 and v0.1.5 in January 2026 there were no releases at all, and that gap is the main reason it lost ground to newer tools. It works, it is stable, and its report format is still one of the clearest, but it has not gained meaningful features in six years and it will not speak HTTP/3.

An example command to make 100000 requests to a server at a concurrency of 100 with hey:

$ hey -n100000 -c100 https://localhost:3000/

wrk

wrk is a HTTP benchmarking tool written in C, with optional request generation and reporting scripted in LuaJIT. It delivers very high load on multicore CPUs and remains the most starred tool of the bunch. Installation still requires building from source with LuaJIT in place.

It is also effectively finished. The last commit to the repository landed in February 2021, and HTTP/2 support never arrived despite being requested for years. In 2026 that means wrk can only tell you about your HTTP/1.1 path, which for most public origins is now the fallback rather than the norm. It is still a fine way to hammer a local service over plain HTTP, and its Lua scripting hook remains more flexible than anything hey or h2load offer.

An example command to load a server at a concurrency of 100 for 60 seconds with wrk:

$ wrk -t12 -c100 -d60s https://localhost:3000/

What has appeared since

The interesting movement over the past few years has been in Rust and Go rewrites of the same idea, plus a clearer split between "how fast can this go" and "how does this behave at a fixed request rate".

oha

oha is a Rust load generator explicitly inspired by hey, and it is the tool that has taken hey's place for most people. It speaks HTTP/1.1 and HTTP/2, has experimental HTTP/3 behind a build feature, draws a live terminal UI with a latency histogram while the run is in progress, and can emit JSON for scripting. It is packaged for Debian, Homebrew and winget, and it is under continuous development with releases every few weeks.

$ oha -n100000 -c100 https://localhost:3000/

bombardier

bombardier is a Go tool built on fasthttp for HTTP/1.1, with an HTTP/2 mode using the standard library client. It is a single static binary with no build step, which makes it the easiest thing to drop into a container or a CI job. Development is slower than oha but it is still maintained.

$ bombardier -n 100000 -c 100 https://localhost:3000/

vegeta and k6

vegeta and k6 solve a different problem. The tools above use a closed model: a fixed number of workers each send the next request as soon as the previous one returns, so when the server slows down the client politely sends less traffic. Real users do not do that. vegeta drives a constant arrival rate instead and reports the latency distribution honestly, which is what you want when the question is "what happens at 5000 requests per second". k6 goes further with scripted scenarios in JavaScript, thresholds, and multi-step user journeys, at the cost of being a load testing platform rather than a one-liner.

$ echo "GET https://localhost:3000/" | vegeta attack -rate=5000 -duration=60s | vegeta report

This distinction matters more than the choice of tool. A closed-model benchmark under-reports tail latency, a problem usually called coordinated omission. If you are publishing a p99 number, use something that holds the request rate fixed.

Conclusion

Modern HTTP load testing tools are more stable than the age old predecessors on high loads and they give better statistics as well. None of them generates organic traffic, but rather reference traffic to a single URL or a small set of them. For complex scenarios you should look at k6 or a SaaS offering.

Of the original three, h2load is the one that has kept up and it is the right answer whenever HTTP/2 or HTTP/3 is involved. hey still works but has been overtaken by oha, which does the same job with a better report and active maintenance. wrk is frozen and HTTP/1.1 only, which is a shrinking slice of the web, though its LuaJIT scripting still has no direct replacement.

As of July 2026 the pragmatic default is oha for quick interactive runs, h2load when the protocol version is the point, and vegeta or k6 when you need a fixed arrival rate and trustworthy tail latency numbers.

-- Pulu Dev Team

ALL ARTICLES