An API can pass every functional test and still fail in production. It returns the right data, with the right status code, against the right schema, and then it falls over the moment a thousand users hit it at once. Functional testing tells you the API is correct. Performance testing tells you it is correct and fast enough to survive real traffic.
This guide explains what API performance testing is, the test types that matter, the metrics to watch, and how to run a performance test step by step in Apidog.
What API performance testing is
API performance testing measures how an API behaves under load: how fast it responds, how many requests it can handle, and at what point it degrades or breaks. It is not about whether the response is correct; that is functional testing. It is about whether the response arrives quickly and reliably when the system is under pressure.
The goal is to find the limits before your users do. Every API has a ceiling, a point where response times climb, errors appear, or the service stops responding. Performance testing locates that ceiling in a controlled environment so you can raise it, plan capacity around it, or at least know it is there.
APIs are a good target for performance testing because they are deterministic and fast to call. There is no browser to render, no UI to wait on. You send a request, you measure the response. That makes API performance tests cheaper to run and more stable than full end-to-end load tests.
The types of performance testing
“Performance testing” is an umbrella. Underneath it are several distinct test types, each answering a different question.
Load testing applies the traffic you actually expect, your normal and peak request volume, and confirms the API handles it within acceptable response times. This is the baseline test most teams run first.
Stress testing pushes past expected traffic, increasing load until the API degrades or fails. The point is to find the breaking point and to see how it breaks. Does it slow gracefully, or does it return errors and lose data?
Spike testing applies a sudden, sharp jump in traffic, the kind a flash sale or a viral moment produces, and checks whether the API absorbs it or collapses. A system that handles steady load can still fail a spike.
Soak testing, also called endurance testing, holds a moderate load for a long period, hours or days, to expose slow problems: memory leaks, connection pool exhaustion, log files filling a disk. These never show up in a five-minute load test.
Smoke testing is the lightweight pre-check: a small load to confirm the API and the test setup are working before you commit to a long, expensive run.
Most teams need load, stress, and soak testing at minimum. Spike testing matters if your traffic is bursty.
The metrics that matter
A performance test produces numbers. These are the ones to read.
Response time is how long the API takes to receive, process, and return a request. Look at percentiles, not just the average. The average can look healthy while the 95th and 99th percentile, the slowest 5% and 1% of requests, are unacceptable. Real users feel the tail.
Throughput is the number of requests the API completes per second. It tells you the real capacity of the system, independent of how many users are connected.
Concurrent users or virtual users is how many simultaneous callers the test simulates. Capacity is often expressed as the maximum concurrency the API sustains before response times cross your budget.
Error rate is the percentage of requests that fail under load. An API that stays fast but starts returning 500s at high concurrency has still failed the test.
Resource utilization, CPU and memory on the server, tells you why performance degrades. If response times climb while CPU sits at 100%, you are compute-bound; if CPU is idle but latency rises, the bottleneck is elsewhere, often a database or a downstream call.
A good performance report ties these together: at this concurrency, throughput peaked, the 95th-percentile response time was this, and the error rate was that.
How to run an API performance test in Apidog
Apidog includes load testing built into the same workspace where you design and functionally test your APIs, so you do not need a separate tool to get started.
Step 1: Pick the endpoint or scenario to test. Choose a single critical endpoint, or a multi-step test scenario that mirrors a real user flow, such as login followed by a data fetch. Testing a realistic flow gives more honest numbers than hammering one endpoint in isolation.
Step 2: Confirm it passes functionally first. Run the request with its assertions once. There is no value in load testing an endpoint that returns the wrong data; fix correctness before measuring speed.
Step 3: Configure the load. Set the number of virtual users and the test duration. Apidog lets you ramp up gradually, simulating users joining over time rather than all at once, which produces a more realistic picture and helps pinpoint the concurrency level where performance turns.
Step 4: Run the test. Apidog executes the load and reports live: response times, throughput, error rate, and how each metric changes as concurrency rises. Watch for the inflection point where response time starts climbing faster than load.
Step 5: Read the results and find the bottleneck. If the 95th-percentile response time crosses your budget at 300 concurrent users, that is your current ceiling. Cross-reference with server CPU and memory to understand the cause. Re-run after a fix to confirm the ceiling moved.
Step 6: For heavier needs, export to JMeter. When you need distributed load generation beyond a single machine, Apidog can export the scenario to JMeter, so you keep the same test definition while scaling the load source.
Download Apidog to run your first load test against an endpoint you already have.
Reading a real performance result
Numbers without interpretation are noise. Take a concrete run: you load test GET /products with virtual users ramping from 0 to 500 over five minutes.
For the first 200 users, the 95th-percentile response time holds steady around 180 ms and throughput rises in step with the load. This is the healthy zone; the API is keeping up. At roughly 280 users, the 95th-percentile time starts climbing, 240 ms, then 400 ms, then 900 ms, while throughput flattens instead of rising. That flattening is the signal: the API has hit its ceiling. Adding more users now produces slower responses, not more completed work. Past 420 users, the error rate creeps above 1% as requests begin timing out.
The verdict is concrete. This API comfortably serves about 250 concurrent users within a 200 ms budget. Its practical ceiling is near 280, and it starts failing around 420. If you expect peak traffic of 200 concurrent users, you have headroom. If you expect 350, you have a problem to fix before launch, not after.
That is what a performance test delivers: not “pass” or “fail,” but a clear map of where the API is comfortable, where it strains, and where it breaks.
Common API performance bottlenecks
When a test exposes a ceiling, the cause is usually one of a few familiar culprits.
Slow database queries are the most common. An unindexed column, an N+1 query pattern, or a missing query limit turns a fast endpoint slow the moment data volume or concurrency rises. If latency climbs while server CPU stays low, suspect the database first.
Blocking external calls drag an endpoint down to the speed of its slowest dependency. An API that calls a payment provider or a third-party service synchronously inherits that service’s latency and its outages.
Connection pool exhaustion appears under sustained load: the API runs out of database connections or HTTP clients and requests queue up waiting. This is a classic soak-test finding.
Inefficient serialization of large response payloads burns CPU. Returning more data than the client needs makes every response slower to build and slower to transfer.
A performance test points at where the ceiling is; pairing it with server-side metrics tells you why.
Building performance testing into your process
A performance test run once before a big launch is useful. A performance test that runs regularly is far more valuable, because performance regresses quietly. A new database query, an added downstream call, or an unindexed column can each add latency that no functional test notices.
Set a response-time and error-rate budget for your critical endpoints, and treat a breach as a failure, the same way you treat a broken assertion. Run a lighter load test as part of CI/CD so a regression surfaces at the pull request, and reserve heavy stress and soak runs for scheduled pre-release testing.
Keep performance tests next to functional tests. When the two live together, every API change gets checked for both correctness and speed, and “it works” and “it works fast enough” stop being separate, easily forgotten questions.
Frequently asked questions
What is the difference between load testing and stress testing? Load testing applies the traffic you expect and confirms the API handles it. Stress testing pushes past that to find the breaking point. Load testing verifies normal operation; stress testing maps the failure mode.
Should I look at average or percentile response times? Percentiles. The average hides the slow tail. The 95th and 99th percentile show what your least-lucky users actually experience, and that is what drives complaints.
Can I performance test an API before the backend is finished? You can test the contract and the design, but meaningful latency numbers need real infrastructure. Use a mock server for early functional work, and run load tests against the real implementation.
How often should performance tests run? Run a light load test in CI on every change to critical endpoints, and full stress and soak tests before each major release. Performance regresses silently, so regular checks beat one big pre-launch run.
