Introduction
Making sure your website performs well under real‑world conditions is critical as traffic grows and user expectations increase. Load testing helps you understand how your application behaves under stress, before performance problems affect real users.
This article explains what load testing is, why it matters, and how to approach it today using modern tools such as k6 and Vegeta, alongside a brief look at the older but still occasionally useful Siege tool.
What Is Load Testing?
Load testing is the practice of simulating concurrent traffic against a web service to evaluate how it performs under expected or extreme usage. Unlike functional testing, load testing focuses on:
- Response time and latency distribution
- Throughput (requests per second)
- Error rates under stress
- System behaviour near capacity limits
The goal is not simply to “break” your site, but to understand where it bends and why.
Load Testing Tools in 2026
| Tool | Best For | Scriptable | Notes |
|---|---|---|---|
| k6 | Automated, CI-friendly testing | Yes (JavaScript) | Actively maintained, excellent developer ergonomics |
| Vegeta | Constant-rate load tests | Limited | Great for quick, predictable RPS testing |
| Siege | Simple ad-hoc tests | No | Lightweight but dated |
For most modern developer-owned workflows, k6 is the most flexible and future-proof choice.
Sidebar: Load Testing, 2015 → 2026
2015
- Load testing was often manual and ad-hoc
- CLI tools like Siege or ApacheBench dominated
- Tests were run locally, rarely automated
- Focus was on “can it survive traffic?”
- Performance issues were usually found late
2026
- Load testing is automated and version-controlled
- Scriptable tools (k6) fit naturally into CI/CD
- Performance budgets and thresholds gate merges
- Focus is on latency percentiles and regressions
- Performance is treated as a first-class feature
What changed? Infrastructure became elastic, deployments became continuous, and user expectations rose. Load testing evolved from a one-off stress exercise into a continuous engineering discipline.
For most modern developer‑owned workflows, k6 is the most flexible and future‑proof choice.
Siege: The Classic Option
Siege is a simple command‑line HTTP load testing tool. It’s useful for quick checks but lacks scripting, assertions, and modern automation features.
Example
sudo apt install siege
siege -c 10 -t 30s https://your-site.example.com
-c 10simulates 10 concurrent users-t 30sruns the test for 30 seconds
Siege reports basic statistics such as throughput and response time, but interpretation and repeatability are limited.
k6: Modern Load Testing for Developers
k6 is a modern load testing tool designed for automation and integration with CI/CD pipelines. Tests are written in JavaScript, making them easy to version, review, and extend.
Installation
brew install k6
Example k6 Script
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
vus: 50,
duration: "30s",
};
export default function() {
const res = http.get("https://your-site.example.com");
check(res, {
"status is 200": (r) => r.status === 200,
});
sleep(1);
}
Run the test:
k6 run loadtest.js
k6 supports ramping profiles, thresholds, HTTP/2, and rich reporting, making it suitable for both local testing and continuous performance monitoring.
Vegeta: Rate‑Based Load Testing
Vegeta focuses on constant‑rate request generation. Instead of defining virtual users, you define a fixed number of requests per second.
Example
Create a file targets.txt:
GET https://your-site.example.com
Run the test:
vegeta attack -rate=100 -duration=30s -targets=targets.txt | vegeta report
Vegeta is ideal when you want predictable traffic patterns without complex scripting.
Choosing the Right Tool
- Quick exploratory test: Siege or Vegeta
- Automated regression testing: k6
- CI/CD performance gates: k6
- Constant, controlled load: Vegeta
For most teams, k6 provides the best balance of power, maintainability, and automation.
Interpreting Results
Key metrics to watch:
- Throughput: how much traffic the system sustained
- Latency percentiles: especially p95 and p99
- Error rate: failed requests under load
- Resource usage: CPU, memory, and I/O during tests
Load testing is most effective when combined with system monitoring to correlate application behaviour with infrastructure constraints.
CI/CD: Run k6 in GitHub Actions (Performance Gate)
If you want load testing to actually protect performance over time, run a small smoke load test on every PR (or on
main) and fail the build when key latency or error metrics regress.
1) Add a k6 test with thresholds
Create perf/smoke.js:
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
vus: 10,
duration: "30s",
thresholds: {
http_req_failed: ["rate<0.01"], // <1% errors
http_req_duration: ["p(95)<800"], // p95 < 800ms
},
};
export default function() {
const url = __ENV.BASE_URL || "https://your-site.example.com";
const res = http.get(url, {
headers: {
// Optional: protect staging with a token
...(__ENV.BEARER_TOKEN ? { Authorization: `Bearer ${__ENV.BEARER_TOKEN}` } : {}),
},
});
check(res, { "status is 200": (r) => r.status === 200 });
sleep(1);
}
The important bit is thresholds, k6 will exit non‑zero if they fail, which is perfect for CI.
2) GitHub Actions workflow
Create .github/workflows/perf-k6.yml:
name: Performance (k6)
on:
pull_request:
push:
branches: [ main ]
jobs:
k6:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup k6
uses: grafana/setup-k6-action@v1
- name: Run k6 smoke test
env:
BASE_URL: ${{ secrets.PERF_BASE_URL }}
BEARER_TOKEN: ${{ secrets.PERF_BEARER_TOKEN }}
run: |
k6 run perf/smoke.js
Notes:
- Point
PERF_BASE_URLat staging, not production. - Keep CI tests short and stable (think 30–60 seconds, low VUs).
- Do deeper tests on a schedule or before releases.
Best Practices
- Define performance goals before testing
- Start with low load and ramp gradually
- Test production-like environments
- Automate performance thresholds
- Re-run tests after significant changes
Conclusion
Load testing has evolved significantly since simple command‑line tools first appeared. While Siege still has niche uses, modern workflows benefit from scriptable, automated tools like k6, with Vegeta providing a useful middle ground for rate‑based testing.
Performance should be treated as a feature, measured, tested, and protected over time. With the right tooling and discipline, load testing becomes a routine part of building reliable web systems.