🎉 GoReplay is now part of Probe Labs. 🎉

Published on 8/2/2026

Mastering apache bench ab: A Practical Guide to Load Testing

- A photo-realistic network operations center with blurred server racks and a faint terminal window displaying performance metrics, featuring "Apache Bench AB" text prominently centered on a solid background block in the golden ratio position, subtle cables and graphs framing the scene while keeping the text sharp and dominant

Apache Bench, better known as just ab, is a dead-simple command-line tool for getting a quick read on your web server’s performance. It’s built to give you a fast impression of how your server handles a ton of requests, all without a complicated setup.

Why Apache Bench Still Matters for Modern Developers

A laptop displaying code and 'AB' on a screen, with a notebook, pen, and plant on a wooden desk. 'Quick Baseline' text is in the background.

Before you fire up a heavy-duty load testing suite, you need a quick and reliable baseline. That’s where Apache Bench shines. It’s a foundational utility that’s still indispensable for any developer or DevOps engineer who needs to measure raw server throughput and latency on the fly.

Its job is simple: hammer a single URL with a high volume of HTTP requests and tell you how the server held up. This simplicity is its biggest advantage, clearly separating it from more sophisticated tools like GoReplay, which are designed to simulate complex user journeys by replaying real traffic.

The Go-To Tool for Initial Health Checks

Think of ab as your first diagnostic. It’s perfect for getting quick answers to critical questions about your infrastructure’s health:

  • Can our server handle a sudden traffic spike? A simple ab test can reveal the breaking point.
  • Did our last deployment kill performance? Comparing ab results before and after a release gives you instant feedback.
  • Is this new server configuration actually better? ab offers a straightforward way to quantify the impact of your changes.

To give you a quick overview, here’s a summary of what ab is all about.

Apache Bench (ab) At a Glance

AspectDescription
PurposeA command-line tool for basic HTTP server benchmarking and stress testing.
Primary Use CasesGetting a quick baseline of server performance, measuring requests per second, and identifying the breaking point of a single endpoint.
Key LimitationsSingle-threaded, cannot simulate complex user journeys, and struggles with modern protocols like HTTP/2 without workarounds.

This table helps frame where ab fits into a modern performance testing toolkit—it’s the starting point, not the final word.

ApacheBench has been a cornerstone of performance testing since it was first bundled with the Apache HTTP Server back in the late ’90s. Originally developed in C as a single-threaded tool, it quickly became the standard for figuring out how many requests per second a server could handle under duress. You can read more about its history on Atlantic.net.

Apache Bench isn’t for simulating realistic user behavior. Its purpose is to stress-test a specific endpoint with repetitive requests to find its raw performance limits.

This focused approach is exactly what makes it the perfect starting point. You use ab to find the raw capacity of your hardware and network stack. Once you’ve established that baseline, you can bring in more advanced tools to test your application logic and database interactions under much more realistic conditions. It’s a vital first step in any serious performance testing workflow.

Getting Your Hands Dirty with Your First Apache Bench Test

Running your first ab test is a lot less intimidating than you might think. It’s a command-line tool, so the first thing is to just get it installed. The good news is that it’s usually bundled in standard packages, making the setup a breeze.

On Linux systems like Ubuntu or Debian, you’ll find it inside the apache2-utils package. This gets you ab along with a few other handy Apache utilities.

  • For Debian/Ubuntu: sudo apt-get install apache2-utils
  • For CentOS/RHEL: sudo yum install httpd-tools

If you’re on a Mac, the path of least resistance is almost always Homebrew. The command is just as simple.

  • For macOS: brew install httpd

Once that’s done, pop open a terminal and run ab -V. You should see the version info pop up, which is your green light that ab is installed and ready to roll.

Crafting Your First Test

With ab installed, you’re ready to run a benchmark. The command structure is pretty intuitive and boils down to a few key flags that tell ab what to do. For a basic test, you really only need to worry about the total number of requests and the concurrency level.

The two flags you’ll use constantly are:

  • -n (number): This is the total number of requests you want to send.
  • -c (concurrency): This tells ab how many requests to run in parallel.

Think of it like this: -n 1000 -c 10 means you’re telling ab to fire off a grand total of 1000 requests, but to do it in batches of 10 at a time until it’s done.

A great starting point is to set the concurrency (-c) to match the number of CPU cores on your server. This gives you a solid baseline for how your machine handles a moderate, parallel load before you really start pushing the envelope.

Let’s put this into practice. Say you want to hit your homepage with 500 total requests, sending 20 of them simultaneously. The command would look like this:

-n: Total number of requests to perform

-c: Number of multiple requests to make at a time

The final argument is always the URL to test

ab -n 500 -c 20 https://your-website-url.com/

Hit enter, and ab gets to work. It will fire off all the requests you specified and, once it’s finished, spit out a detailed summary right there in your terminal. We’ll dive into what all that output means in the next section.

How to Actually Interpret Apache Bench Results

Running an ab test is easy. The real skill is in decoding the wall of text it spits back at you. That output tells a detailed story about how your server behaves under pressure, and learning to read it is the key to making smart optimizations.

This diagram breaks down the core components of a basic Apache Bench command, illustrating how the total number of requests (-n) and the concurrency level (-c) combine to kick off a test.

Diagram illustrating Apache Bench command flow, key parameters, requests (n), and concurrency (c) with examples.

This simple flow—turning a few command-line flags into a powerful stress test—is the foundation of every benchmark you’ll run.

The Big Picture Throughput Metrics

When you first glance at the results, a few key numbers will jump out. Think of these as your high-level dashboard for server throughput and overall health.

  • Requests per second: This is the headline metric. It’s a straightforward measure of how many requests your server successfully handled each second during the test. A higher number is almost always better, but it’s meaningless without the context of latency and error rates.

  • Time per request: This metric is often shown in two ways. The first is the average time across all concurrent requests, but the second one (usually in parentheses) is the real gem—it shows the average time a single user would have to wait. I always focus on that second number because it’s a much closer reflection of the actual end-user experience.

  • Transfer rate: This shows you how much data was flying across the wire per second. It’s incredibly useful for figuring out if network saturation is your bottleneck, especially when you’re serving up large files or API payloads.

Latency Percentiles Tell the Real Story

Throughput is a great starting point, but latency reveals what your users are actually experiencing. Your server might handle 5,000 requests per second, but if 10% of those users are staring at a loading spinner for five seconds, you have a major problem on your hands.

The “Percentage of the requests served within a certain time” table is where you find these golden nuggets of information.

The latency percentile table is easily the most critical part of the ab output. It cuts through the noise of simple averages to show you the performance experienced by the majority of your users, as well as the outliers you can’t afford to ignore.

Keep an eye out for these key milestones in the table:

  • 50% (Median): Half of your requests were faster than this value. It’s a good baseline for typical performance.
  • 90% / 95% / 99%: These numbers reveal the “long tail” of your response times. The 99% value is especially telling, as it represents the experience of your least satisfied users. A massive jump between the 95th and 99th percentile is a huge red flag, often pointing to intermittent bottlenecks like database contention or garbage collection pauses.

Understanding these detailed latency metrics is what gives DevOps teams granular insight into request-response cycles. When ab calculates Time per request and Requests per second, it aggregates the data into min, mean, standard deviation, median, and these crucial percentiles.

For example, a real-world test against Nginx with 800 requests at 300 concurrent connections might yield 4354.95 req/sec, with 99% of requests finishing in under 70 ms. You can explore more about these detailed ab metrics at Datadog.

Spotting Red Flags in the Output

Beyond the primary metrics, you need to scan the results for clear warning signs.

A high number of Failed requests is the most obvious red flag. It means your server is buckling under the load, dropping connections, or returning errors. You’ve just found a hard limit, and now it’s time to figure out why.

Another, more subtle metric to watch is the standard deviation (sd) of the connection times. A high standard deviation, even with a decent average, means your response times are all over the place. This kind of inconsistency creates a poor and unpredictable user experience, often suggesting underlying stability issues that need a much deeper look.

To make sense of it all, here’s a quick reference table for the most important metrics in your ab output.

Key Apache Bench Output Metrics Explained

MetricWhat It MeansWhat to Look For
Requests per secondYour server’s raw throughput. How many requests it processed each second.A higher number is better, but watch for a drop as concurrency increases—this signals a bottleneck.
Time per request (mean, across all concurrent requests)The average response time per user if they were making requests one after another. This reflects the user-facing latency.A low, stable number. If this number climbs rapidly with concurrency, you have a scaling problem.
50% Latency (Median)The midpoint of your response times. Half of all requests were faster than this.A good baseline for “typical” performance. Should be close to your service level objectives (SLOs).
99% LatencyThe “worst-case” experience for the vast majority of your users. Only 1% of requests were slower than this.A sudden, large jump from the 95% value. This indicates “long-tail” latency problems that affect a small but significant number of users.
Failed requestsThe number of requests that resulted in an error (e.g., connection refused, timeout, non-2xx response).Anything greater than 0 is a serious red flag. Your server is failing under load.
Standard Deviation (sd)How consistent or erratic your response times are.A low number is good (consistent performance). A high number means wildly fluctuating response times, even if the average looks okay.

By focusing on these specific metrics, you move beyond just “how fast?” and start asking the more important questions: “How consistent?” and “What’s the experience for my unhappiest user?” That’s where real performance engineering begins.

Advanced Commands for Realistic Load Testing

Computer screen showing 'Advanced Commands' and 'AB' letters, with a wireless keyboard on a wooden desk.

Basic GET requests are a great starting point, a quick sanity check to see if your server is alive. But let’s be honest, modern applications are way more complex.

To get a real sense of how your system will hold up, your benchmarks have to look like real-world traffic. We’re talking API calls, authenticated sessions, and efficient connections—not just hammering the homepage. The good news is that ab has a whole suite of flags to help you build these more sophisticated scenarios.

Testing API Endpoints with POST Requests

Most of the heavy lifting in your application probably happens at API endpoints that handle POST requests carrying a payload, like a JSON object. To simulate this, ab uses two flags that work in tandem:

  • -p (postfile): This flag tells ab where to find a local file containing the request body you want to send.
  • -T (Content-type): This flag sets the Content-Type header, letting the server know what kind of data is coming its way. For APIs, this is almost always going to be application/json.

Imagine you have a file named payload.json with this content: { “username”: “testuser”, “comment”: “This is a great post!” }

To throw this data at your /api/comments endpoint, you’d run a command like this: ab -n 500 -c 10 -p payload.json -T ‘application/json’ https://your-api.com/api/comments This command sends 500 requests with 10 running concurrently, each one delivering that JSON payload and correctly identifying it. Now you’re testing your actual backend logic, which is far more valuable.

Simulating Modern Browser Behavior

Modern browsers are smart. They don’t open a brand new TCP connection for every single asset on a page. Instead, they use Keep-Alive connections to pipe multiple HTTP requests through the same channel, which is way more efficient. You can mirror this behavior in ab with the -k flag.

Using the -k flag for Keep-Alive connections gives you a much more accurate benchmark for real-world browser traffic. It cuts down the overhead from TCP handshakes, so you can measure what your application can truly handle.

On top of that, many endpoints require authentication or other custom headers. The -H flag is your friend here, letting you add any header you need, like an Authorization token.

Here’s a practical example combining these flags to test an authenticated endpoint that requires a user profile: ab -n 1000 -c 50 -k -H ‘Authorization: Bearer your-jwt-token’ https://your-app.com/api/v1/profile

Exporting Data for Deeper Analysis

The final summary ab spits out is handy, but sometimes you need to get into the weeds and analyze the request-level data. The -g flag is the key. It tells ab to dump the raw data for every single request into a Gnuplot-ready file—which is just a fancy way of saying a tab-separated values (TSV) file.

This raw data file gives you columns like starttime, seconds, ctime (connection time), dtime (processing time), and ttime (total time). You can easily pull this into a spreadsheet or plotting software to visualize trends, spot outliers, and see how performance changed over the course of the test.

When you’re digging into these results, especially with distributed systems, it’s critical to understand how things like load balancing can affect your numbers. For an even more powerful approach, check out our guide on how to replay production traffic for load testing.

Integrating Apache Bench into Your Testing Workflow

While Apache Bench is a fantastic tool for getting a quick performance read, its real value shines when you understand its specific place in a broader testing strategy. Think of it as your first line of defense—a quick and dirty way to find the raw breaking points of your infrastructure.

But it’s critical to recognize where this simple benchmarking ends and comprehensive load testing begins.

ab is essentially a stress test for a single component. It’s built to answer very specific questions like, “How many raw requests can this API endpoint handle before it keels over?” or “Did my last deployment improve the raw throughput of this service?” This laser-focused approach is perfect for isolating and measuring the performance of individual parts of your system. It excels at finding the absolute performance ceiling of your web server or a new load balancer configuration.

Transitioning from Benchmarking to Realistic Load Testing

Once you’ve used ab to establish a baseline, the next logical step is to simulate how real users actually interact with your application. This is where you’ll start to see the limitations of a simple tool like ab. It was never designed to replicate complex user journeys that involve sequential API calls, maintain session state, or send varied request payloads.

For example, a typical user signup flow is anything but simple. It might involve several distinct steps:

  • POST to /api/users to create the new account.
  • POST again to /api/login to get a session token.
  • GET /api/dashboard to load their personalized view.

Simulating this kind of multi-step, stateful interaction is well beyond what ab can do.

Introducing Traffic Replay for Authentic Scenarios

To really validate your application logic and database performance under authentic conditions, you need a tool that mirrors actual user traffic. This is exactly where traffic-replay tools like GoReplay come into the picture. Instead of hammering a single URL with repetitive, synthetic requests, GoReplay captures real user traffic from your production environment and replays it against your testing setup.

This strategic approach—using ab for initial stress tests and GoReplay for realistic, application-level load testing—gives you a clear path to maturing your performance validation. It ensures your system is not just fast but also stable under the messy, unpredictable pressure of real-world use.

When you’re ready to make Apache Bench a core part of your process, understanding the broader principles of how to perform backend testing will be invaluable. This layered strategy helps you move from generic benchmarks to high-fidelity simulations that genuinely reflect user interactions. You can also explore more options in our guide to open-source load testing tools.

Common Questions About Apache Bench

Getting started with a new tool always unearths a few questions. Here are some quick answers to the most common things people run into when they first start using ab.

Can I Use Apache Bench for HTTPS Websites?

Yes, absolutely. Apache Bench natively supports SSL/TLS, so all you need to do is use an https:// URL instead of http:// in your command.

Just remember that the TLS handshake adds a bit of computational overhead. You’ll almost certainly see lower requests per second and slightly higher latency compared to an identical test against an unencrypted HTTP endpoint. This is totally normal and actually gives you a more realistic picture of what real users experience.

What Does “Connection Reset by Peer” Mean?

If you see an error like apr_socket_recv: Connection reset by peer, it’s a huge clue that you’ve hit a serious bottleneck. This message pops up when the server unexpectedly terminates the connection while ab is still waiting for a response.

A few things could be happening here:

  • The web server or your application process simply crashed under the load.
  • A firewall or load balancer in front of your server is actively dropping connections it deems excessive.
  • Your application has hit an internal concurrent connection limit and is flat-out refusing to talk to new clients.

Discovering this error is actually a good thing. It means your test just uncovered a critical stability issue you need to fix.

How Is ab Different from Tools Like JMeter or Gatling?

The main difference comes down to scope and complexity. Apache Bench is a simple, no-frills command-line tool built to do one thing: hammer a single URL with HTTP requests. It’s fantastic for quick, focused stress tests to get a performance baseline.

In contrast, tools like JMeter and Gatling are full-blown load testing frameworks. They let you build complex test plans with scripting, conditional logic, and realistic user journeys, all wrapped up with detailed graphical reports.

Think of it this way: ab tells you how fast your car goes in a straight line. JMeter or Gatling can simulate thousands of drivers navigating a complex city, each with a different destination. For a quick speed check, ab is perfect. For understanding how your whole system behaves under a realistic, complex load, you’ll want to reach for something bigger.


At GoReplay, we believe in testing with real traffic. While ab is perfect for baselines, our open-source tool allows you to capture and replay real user sessions, giving you the confidence to deploy changes without surprises. Discover how traffic replay can transform your testing workflow.

Ready to Get Started?

Join these successful companies in using GoReplay to improve your testing and deployment processes.