GUIDE / performance
How to Do API Load Testing
Learn how to do API load testing: design realistic scenarios, set thresholds, run concurrent users, read metrics, and avoid false confidence on REST APIs.
API load testing is how you prove an API can handle real concurrent demand without turning into guesswork the week before launch. A functional suite that passes with one user does not tell you what happens when hundreds of clients call login, search, checkout, and webhooks at the same time. Latency climbs, connection pools fill, caches miss, and downstream services start timing out. Load testing makes those risks visible early.
This guide shows how to do API load testing from first principles: define goals, design realistic scenarios, choose tools, model concurrent users, set thresholds, run safely, interpret results, and avoid the mistakes that create false confidence. You will also get checklists, sample scripts, and a practical path you can reuse on REST and similar HTTP APIs.
What API Load Testing Actually Measures
API load testing applies controlled concurrent traffic to API endpoints or multi-step API journeys and measures whether the system still meets performance and reliability goals.
You are usually answering questions like:
- Can the API handle expected peak request rates?
- Do p95 and p99 latency stay inside the service level objective?
- Does the error rate stay acceptable under load?
- Does throughput scale as virtual users increase, or does it plateau early?
- Which dependency saturates first: app servers, database, cache, queue, or third party?
- Does authentication, pagination, or large payloads change the picture?
API load testing is not the same as:
- Unit or integration tests that check correctness with a single thread.
- Chaos testing that intentionally breaks infrastructure.
- Browser performance testing that includes rendering and Core Web Vitals.
- Security testing that probes for injection or broken access control.
Those practices matter, but they answer different questions. Load testing is about capacity, stability, and response behavior under concurrent use.
If you need the broader vocabulary of load, stress, soak, and spike shapes, read load vs stress vs soak vs spike. This article focuses on the API load path you will run most often.
Why API Load Testing Matters for QA and Engineering
APIs are the backbone of modern products. Mobile apps, single page apps, partner integrations, batch jobs, and internal microservices all create concurrent demand. When an API degrades, the UI often looks "broken" even though the front end code is fine.
Teams that skip API load testing usually discover problems too late:
- Black Friday checkout timeouts.
- Login storms after a marketing campaign.
- Search latency spikes when catalog size grows.
- Webhook backlogs after a partner integration launches.
- Database connection exhaustion after a release that adds N+1 queries.
Good API load testing reduces release risk, informs capacity planning, and gives product owners a clearer language for "fast enough." It also protects developers from optimizing the wrong thing. A prettier dashboard mean is less useful than a stable p95 under a known peak profile.
Prerequisites Before You Generate Traffic
Do not start by opening a tool and ramping users. Start by making the test safe and meaningful.
1. Permission and environment
You need explicit approval for the target environment. Prefer a dedicated performance environment that mirrors production topology as closely as budget allows. Shared staging is risky because other teams' tests pollute your signal, and your load can break their work.
Never run open ended load against production systems you do not own. If production is the only realistic option, require change control, rate limits, traffic shaping, off peak windows, and instant abort criteria.
2. Goals and service level objectives
Write down what "good" means before the first run:
| Goal type | Example for a checkout API |
|---|---|
| Latency | p95 under 400 ms, p99 under 800 ms at peak |
| Reliability | Error rate under 0.5 percent for 5xx and timeouts |
| Throughput | Sustain 800 successful checkouts per minute |
| Scalability | Linear throughput growth up to 2x baseline with no error cliff |
| Stability | No memory growth or connection leak over a 2 hour soak |
If stakeholders cannot agree on numbers, document assumptions and ranges. A test without goals becomes a chart collection exercise.
3. Representative journeys
Pick journeys that matter commercially and technically:
- Authentication and token refresh.
- Search and listing with realistic filters.
- Create and update resources.
- Checkout, payment intent, or booking confirmation.
- High volume read endpoints behind the homepage.
- Webhook or callback receivers if they are critical.
A single GET /health under load is useful as a smoke check, not as product confidence.
4. Test data strategy
Load tests fail for boring data reasons:
- Shared users get rate limited or locked.
- Unique constraints collide on email or order IDs.
- Cache hit rates are unrealistically high or low.
- Test accounts lack inventory, permissions, or feature flags.
Plan data factories, ID ranges, cleanup jobs, and seed scripts. Document which data is disposable and which must stay.
5. Observability
Client side metrics are incomplete without system visibility. Before the run, confirm you can see:
- Application CPU, memory, GC, and thread pools.
- Database CPU, slow queries, locks, and connection pool usage.
- Cache hit rate and eviction.
- Queue depth and consumer lag.
- Downstream dependency latency and error rates.
- Autoscaler events if you use them.
API Performance Testing Checklist
Use this API performance testing checklist before calling a suite ready:
- Target environment and approval are documented.
- Baseline functional correctness is already green.
- Journeys represent real peak usage, not only happy path GETs.
- Authentication model matches production patterns.
- Think time and pacing are realistic.
- Payload sizes and query patterns match production distributions.
- Checks assert status codes and critical response fields.
- Thresholds encode latency and error budgets.
- Abort rules stop runaway tests.
- Server and dependency dashboards are ready.
- Results will be compared to a previous baseline.
- Ownership for triage and retest is clear.
How to Design an API Load Scenario
A useful scenario models what clients actually do, not what is easiest to script.
Map the real traffic shape
Ask product analytics and backend owners:
- What is normal weekday traffic?
- What is seasonal or campaign peak?
- Which endpoints dominate request volume?
- Which endpoints dominate latency or cost?
- Are arrivals steady or bursty?
- How long do users think between actions?
Convert that into a load model. Two common models are:
- Virtual user (VU) model: N concurrent clients each running a journey with think time.
- Arrival rate model: N requests or iterations started per second, independent of how long each iteration takes.
VU models feel intuitive. Arrival rate models often match gateway traffic better. Many teams use both: VU based multi-step journeys and arrival rate for hot single endpoints.
Keep journeys realistic
Weak journey:
GET /products
GET /products
GET /products
Stronger journey:
1. Authenticate or reuse a short lived token.
2. Search products with a realistic query distribution.
3. Open a product detail page.
4. Add item to cart.
5. Start checkout.
6. Confirm order with valid test payment data.
7. Poll order status once or twice.
The second journey stresses auth, catalog, cart, inventory, payments, and consistency. It also surfaces bottlenecks that a single endpoint never reveals.
Separate correctness from capacity
Every load script should still check correctness. If the API returns 200 with an empty body or a failed business status, a pure latency graph can look fine while users fail.
Checks to include:
- HTTP status in the expected set.
- Response schema or critical fields present.
- Business success markers such as
"status":"CONFIRMED". - Latency of individual steps in multi-step flows.
- Token expiry and refresh success rates.
Checks tell you quality during the run. Thresholds decide pass or fail for the whole test.
Choosing API Load Testing Tools
Tool choice should follow team skills and protocol needs. For a full comparison, see performance testing tools. Here is the practical shortlist for APIs:
| Tool | Best fit | Scripting | CI friendliness | Watch out for |
|---|---|---|---|---|
| k6 | Modern HTTP APIs, developer owned tests | JavaScript | Excellent thresholds and exit codes | Browser scenarios are heavier |
| JMeter | Mixed protocols, GUI design, enterprise plugins | GUI + code elements | Good, but heavier to operate | Resource hungry generators |
| Gatling | High throughput JVM shops | DSL (Java/Kotlin/Scala) | Strong reporting | Steeper learning for some QA teams |
| Locust | Python teams, flexible scenarios | Python | Solid | Generator scaling needs planning |
| Artillery | Node teams, YAML plus JS | YAML/JS | Good for many web APIs | Complex enterprise ecosystems may need more |
If your team is starting fresh on REST APIs in 2026, k6 is often the fastest path to maintainable API load testing. If non developers must own complex multi-protocol suites, JMeter remains valuable.
How to Load Test REST APIs Step by Step
Step 1: Prove a smoke script
Start with one endpoint and one virtual user. Confirm auth works, data works, and checks pass. This saves hours of debugging at 200 VUs.
Example k6 smoke sketch:
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
vus: 1,
duration: '30s',
thresholds: {
http_req_failed: ['rate<0.01'],
http_req_duration: ['p(95)<500'],
},
};
const BASE = __ENV.BASE_URL;
export default function () {
const res = http.get(`${BASE}/api/v1/health`);
check(res, {
'status is 200': (r) => r.status === 200,
});
sleep(1);
}
Step 2: Add authentication the production way
Do not hardcode one immortal admin token unless that is how real clients work. Prefer:
- Client credentials for service to service APIs.
- Password or magic link login for user journeys, with token reuse.
- API keys in headers when that is the product contract.
- Short lived JWTs with refresh logic if clients refresh in production.
Auth endpoints often become the first bottleneck. Measure them explicitly.
Step 3: Parameterize data
Use environment variables for base URLs, credentials, and profile names. Feed product IDs, search terms, and user credentials from CSV or shared arrays. Avoid every VU creating the same unique email.
Step 4: Add think time and pacing
Humans and clients do not hammer endpoints with zero delay forever. Without think time, a handful of VUs can create unrealistic request rates and overstate capacity risk or hide real concurrency issues, depending on the system.
Use realistic sleeps between steps. For pure capacity experiments on a single endpoint, document that you intentionally removed think time.
Step 5: Define load profiles
Common API profiles:
| Profile | Intent | Example shape |
|---|---|---|
| Smoke | Script validity | 1 to 5 VUs for 1 to 5 minutes |
| Baseline | Current expected load | Ramp to normal peak, hold 10 to 20 minutes |
| Peak load | Agreed busy period | Ramp to peak, hold long enough for stability |
| Spike | Sudden burst | Jump to 2x to 5x quickly, observe recovery |
| Soak | Endurance | Moderate load for hours |
Do not run a 30 second spike and call the release performance ready.
Step 6: Set thresholds that match product risk
Examples:
http_req_failed < 1%http_req_duration p95 < 400msfor a read APIhttp_req_duration p99 < 1sfor a complex write API- custom metric: checkout success rate > 99%
Thresholds should fail the build or the test job. Soft reports that nobody reads do not protect users.
To set realistic latency targets, calibrate these thresholds with what is a good response time for the endpoint and user journey.
Step 7: Run, observe, abort if needed
During the run, watch:
- Client error rate and latency percentiles.
- Target CPU and memory.
- Database connections and slow query count.
- Queue depth.
- Third party rate limits.
Abort if error rate explodes, disk fills, or you are harming a shared environment.
Step 8: Interpret results with a decision
A complete interpretation includes:
- Did the test run the intended load?
- Did functional checks stay healthy?
- Did latency percentiles meet goals?
- Did throughput meet goals?
- What saturated first?
- What is the release recommendation?
For a deeper reading method, use how to read a performance test report.
Concurrent Users API Testing: Doing the Math
People often confuse concurrent users with requests per second.
Rough relationship:
requests per second ≈ (concurrent VUs × requests per iteration) / iteration duration in seconds
If one VU runs a 20 second journey that makes 5 HTTP calls, each VU contributes about 0.25 requests per second.
To reach 100 requests per second with that journey:
needed VUs ≈ 100 / 0.25 = 400 VUs
This is why "we tested with 50 users" is meaningless without journey length, think time, and request count. Always report:
- Virtual users or arrival rate.
- Requests per second achieved.
- Journey definition.
- Duration and ramp shape.
- Environment size.
Multi-Step API Journey Example
Here is a conceptual authenticated flow structure you can adapt in k6, JMeter, Gatling, or Locust:
Setup:
- Resolve BASE_URL and test credentials
- Optionally warm caches with a short prelude
Iteration:
1. Login or reuse cached access token
2. Search catalog with weighted queries
3. Open product detail by ID from search
4. Add to cart
5. Create checkout session
6. Confirm payment with test method
7. Assert order id and status
8. Sleep think time 1 to 3 seconds
Teardown:
- Cancel unpaid test orders if needed
- Rotate or invalidate temporary tokens
Weight queries and products so a tiny hot subset does not create an unrealistic cache fantasy, unless production really is that skewed and you are modeling it on purpose.
Environment Parity and Fairness
Perfect production clones are rare. Still, document differences:
| Factor | Why it matters |
|---|---|
| Instance size and count | Capacity numbers do not transfer 1:1 |
| Database size | Query plans change with data volume |
| Cache warmth | Cold starts look worse than steady state |
| Third party sandboxes | Sandboxes may be slower or rate limited differently |
| Feature flags | Missing flags change code paths |
| Async workers | Fewer consumers create artificial backlogs |
When parity is weak, treat results as relative: "this release is 30 percent slower than last release on the same box," not "production will handle exactly 12,000 RPS."
CI and Continuous API Load Testing
Load tests belong in the delivery system, but not every profile belongs on every commit.
Practical split:
- Pull request / merge: tiny smoke load, strict correctness checks, coarse latency thresholds.
- Nightly: baseline or peak profile on the performance environment.
- Pre-release: full peak, spike, and optionally soak.
- Post-incident: regression profile that reproduces the failure mode.
Store scripts in Git. Version thresholds. Publish HTML or dashboard links in the pipeline. Fail the job when thresholds breach.
If you want a hands-on tool path after this methodology article, follow the k6 load testing tutorial.
How to Report API Load Results to Stakeholders
Engineers need charts. Stakeholders need decisions.
A one page summary template:
Test: Checkout API peak load
Date: 2026-07-09
Environment: perf-eu-1 (2x app, 1x db, redis)
Profile: ramp 0->200 VUs in 10m, hold 20m
Goals: p95 < 400ms, errors < 0.5%, 600 checkouts/min
Result: FAIL
Evidence:
- Achieved 520 checkouts/min (goal 600)
- p95 710ms during hold
- error rate 1.8% (mostly 503 from inventory service)
- DB CPU 55%, inventory service CPU 92%
Decision: Do not release peak campaign config
Next actions:
1. Scale inventory service and retest
2. Add cache for stock reads
3. Re-run same profile after fix
Lead with the decision. Support it with numbers. Avoid dumping twenty unlabeled graphs into a Slack thread.
Common Mistakes in API Load Testing
Mistake 1: Load testing only the health endpoint
/health or /ping often bypasses business logic, auth, and database work. Green health latency can coexist with a failing checkout API.
Mistake 2: No functional checks under load
If you only measure transport success, you can miss HTTP 200 responses that return business failures, partial writes, or empty collections.
Mistake 3: Unrealistic data and cache behavior
Replaying one product ID forever can make Redis look heroic. Using all brand new users forever can make auth and DB look worse than production. Model the real mix.
Mistake 4: Ignoring think time
Zero think time creates artificial request storms. That can be useful for stress discovery, but it is not the same as expected load.
Mistake 5: Changing too many variables between runs
If you change code, instance size, dataset, and script logic in one go, you cannot explain the delta. Change one major variable at a time when baselining.
Mistake 6: Treating average latency as the goal
Averages hide tail pain. Users feel p95 and p99. So do mobile clients on poor networks talking to an already slow API.
Mistake 7: No abort criteria
A broken test can thrash a shared cluster for hours. Define stop conditions for error rate, saturation, and cost.
Mistake 8: Skipping correlation with server metrics
Client charts show symptoms. Server metrics show causes. Without both, teams optimize randomly.
Mistake 9: Running once and declaring victory
Performance results have variance. Repeat important profiles, especially after tuning, and compare against a saved baseline.
Mistake 10: Forgetting third party dependencies
Payment providers, email APIs, KYC services, and partner inventories often dominate latency. Mock them intentionally when measuring your system, or measure them explicitly when the contract includes them. Do not mix those goals silently.
Worked Example: From Goal to Decision
Imagine a booking API with this goal:
During campaign peak, the system must create 300 bookings per minute with p95 under 500 ms and total error rate under 1 percent.
Process:
- Confirm campaign peak assumptions with marketing and analytics.
- Build a journey: search availability, lock slot, create booking, confirm.
- Seed inventory for many slots so tests do not serialize on one record.
- Run smoke with 5 VUs.
- Run baseline at 150 bookings/min.
- Run peak at 300 bookings/min.
- Observe that p95 is 480 ms but errors are 2.4 percent on confirm because of unique constraint collisions in test data.
- Fix data uniqueness, re-run, errors drop to 0.3 percent, p95 rises to 620 ms.
- Find DB CPU high on availability search.
- Add index, re-run peak, p95 430 ms, errors 0.2 percent, throughput goal met.
- Mark release candidate pass for this profile, then schedule a soak before the campaign weekend.
Notice the first failure was a test data bug, not production capacity. Good process prevents a wrong scale out decision.
API Load Testing Anti-Patterns vs Better Habits
| Anti-pattern | Better habit |
|---|---|
| One huge mystery run before release | Layered smoke, baseline, peak, spike, soak |
| Tool demo with no thresholds | Pass fail thresholds tied to SLOs |
| Only gateway averages | Per endpoint percentiles and business success metrics |
| Production surprise load | Approved windows and dedicated perf envs |
| Scripts only one person understands | Tests as code in Git with README and owners |
| Optimize based on a single chart | Correlate client and system evidence |
Practice Path on QABattle
Theory sticks when you practice measurement judgment. After you draft your first script locally, open the battle arena and use performance style challenges to sharpen how you explain bottlenecks, thresholds, and tradeoffs. If you are building broader QA skills around APIs and performance, create an account and track progress across related practice paths.
Final Workflow You Can Reuse
When someone asks you to "do API load testing" this week, use this sequence:
- Define the business question and numeric goals.
- Choose journeys that represent peak risk.
- Secure environment access and observability.
- Prepare realistic data and auth.
- Write a smoke script with checks.
- Add load profiles and thresholds.
- Run baseline, then peak, then any needed spike or soak.
- Correlate client metrics with system metrics.
- Decide pass, fail, or conditional release.
- Save the baseline and automate the smoke profile.
API load testing is not about generating impressive request charts. It is about making a defensible statement: under this expected concurrent demand, with this data and this environment, the API meets the reliability and latency promises we care about. When you can make that statement with evidence, load testing has done its job.
If you remember one rule, remember this: realistic journeys, clear thresholds, and correlated metrics beat raw virtual user counts every time.
FAQ
Questions testers ask
What is API load testing?
API load testing measures how an API behaves under expected concurrent traffic. You generate virtual users or request rates, exercise realistic endpoints and data, then judge latency, errors, and throughput against agreed goals. It is not a functional unit test. It answers capacity and stability questions before users do.
How do you load test REST APIs?
Pick a representative journey, script authenticated requests with realistic data and think time, define a load profile, add checks for status and payload correctness, set latency and error thresholds, run against a dedicated environment, and correlate results with server metrics. Start with a smoke profile before full peak load.
Which tool is best for API load testing?
For most modern API teams in 2026, k6 is a strong default because scripts are code, thresholds fail CI cleanly, and virtual users are efficient. JMeter fits GUI heavy or mixed protocol suites. Gatling and Locust are excellent when the team already lives in JVM or Python. Choose for maintainability and ownership, not only peak throughput demos.
What metrics matter in API load testing?
Prioritize error rate, throughput, and latency percentiles such as p95 and p99. Track request rate, timeouts, and business success metrics like order created or login success. Average response time alone is not enough. Correlate client metrics with CPU, memory, database, pool usage, and downstream latency.
How many concurrent users do I need for an API load test?
Base concurrency on expected peak traffic, not a random large number. Convert peak requests per second into virtual users using think time and journey length. Validate with product analytics and capacity planning. Running 10,000 users against a tiny staging box proves little about production readiness.
Can I run API load tests in CI?
Yes, but keep CI profiles short and safe. Use a smoke load with low virtual users and strict thresholds on every pull request or nightly build. Schedule fuller peak and soak tests against a dedicated environment. Never fire uncontrolled load at shared staging or production without approval and guardrails.
RELATED GUIDES
Continue the route
k6 Load Testing Tutorial
k6 load testing tutorial with scripts, stages, thresholds, checks, CI setup, metrics, and browser vs HTTP guidance for practical API performance tests.
Performance Testing Tools: JMeter vs k6 vs Gatling vs Locust
Compare performance testing tools in 2026: JMeter vs k6 vs Gatling vs Locust, open source load testing choices, and picks for APIs and microservices.
Load vs Stress vs Soak vs Spike Testing
Compare load vs stress vs soak vs spike testing with a types chart, when to run each, endurance tips, and practical scenario examples for QA teams.
How to Read a Performance Test Report
Learn how to read a performance test report: interpret p95 and p99, error rates, throughput vs latency graphs, and find bottlenecks from load test results.