Skip to main content

How to Cut API Response Times With Targeted Load Testing

How to Cut API Response Times With Targeted Load Testing

To cut API response times, load test the endpoint users complain about, split its time by dependency, shorten the critical path (the longest chain of waits), and retest the same scenario after each change. Parallelizing independent calls and caching slow, rarely changing data are the two changes that most often move the number.

This post was first published as a case study. The company and the figures in that version could not be verified, so it has been rewritten as a how-to. The numbers below are arithmetic examples, not results from a real customer.

Key takeaways

  • Measure where one request spends its time before changing code. The slowest dependency is often not the one the team suspects.
  • Response time of calls made one after another is their sum. For independent calls run together it is the slowest one.
  • Caching only helps if it shortens the critical path, and the p95 only moves when the hit rate is high enough.
  • Retest with the same load after every change, and judge by p95 and p99, not the average.

How do you find what makes an API slow?

Start from one endpoint with a measured problem, not from the whole API. Pick the one with the worst p95 response time or the most user complaints, and run a load test against it at a realistic request rate. Then look at where one request spends its time: your own code, the database, and each outbound call to another service.

Two sources give you that split. Distributed tracing or timing logs inside the service show time per dependency. A cloud load test shows how the whole response time behaves as load rises. LoadFocus load testing runs tests from 25 cloud regions and reports response time with 50th, 90th and 99th percentiles per run, and thresholds on p95 and p99 response time, error rate and throughput let you fail a run automatically (loadfocus.com/load-testing, read 2026-10-23). The split of a single request into DNS, connect, TLS and server wait is covered in how to reduce API latency with distributed load testing, so this post starts where that one ends: the server wait is large, and you need to know why.

Diagram of an API request passing through a load balancer, web server and application server to a database and an external service, with the slow points marked

Why is the database often not the problem?

Teams usually suspect the database first, because queries are the part they know how to tune. It is a fair first guess and sometimes right, but it is only a guess until the timing is split by dependency. An endpoint that calls other services can spend most of its time waiting for them while the database answers in a few milliseconds.

A worked example, with invented numbers. An endpoint builds a dashboard response from three upstream services and its own logic:

StepTime
Call A (user settings)120 ms
Call B (analytics summary)240 ms
Call C (notifications)180 ms
The service’s own work (including its database query)60 ms

Run one after another, the total is 120 + 240 + 180 + 60 = 600 ms. The upstream calls account for 540 of those 600 milliseconds, which is 90 percent. Tuning the 60 ms of own work, even to zero, saves at most 10 percent. That is the whole case for measuring first.

How much does parallelizing independent calls save?

Calls that do not depend on each other’s results can run at the same time. The wait is then the slowest of them, not the sum. In the example, A, B and C only need the user id, so they can start together:

VersionCalculationResponse time
Sequential120 + 240 + 180 + 60600 ms
Parallelmax(120, 240, 180) + 60300 ms

That halves the response time with no new infrastructure. Two limits apply. Calls that need an earlier call’s output cannot be moved, and calls with side effects (writes, payments) need care before they run together. Also watch the upstream service’s rate limit: three calls at once per request is three times the burst. The post on common causes of API rate limiting explains how that shows up.

Sequential API calls adding up to A+B+C compared with parallel calls taking only the longest one

What should you cache, and when does it help?

After parallelizing, the critical path is call B at 240 ms. Caching call A (120 ms) would change nothing, because B still takes 240 ms. The useful target is the slowest call on the path: B, if the analytics summary changes rarely enough to store for a while.

Say B is served from a cache with 90 percent of requests hitting it and a near-zero cost on a hit. Then the critical path on a hit becomes max(120, 0, 180) = 180 ms, plus 60 ms of own work, so 240 ms. On a miss it is the same 300 ms as before.

Cache hit rateMean response timep95 response time
No cache300 ms300 ms
90%0.9 x 240 + 0.1 x 300 = 246 ms300 ms
96%0.96 x 240 + 0.04 x 300 = 242 ms240 ms

The mean barely moves, and at a 90 percent hit rate the p95 does not move at all, because 10 percent of requests are still misses and the 95th percentile falls inside them. Only when misses drop below 5 percent does the p95 follow. This is why you check percentiles after a caching change, and why a load test with varied request data matters: a test that repeats one request flatters the cache.

Decide what can be stale, and for how long. Settings that change on a profile edit can be cleared on that edit; a summary that is recomputed hourly can expire hourly. When a popular entry expires and many requests rebuild it at once, they all hit the slow call together (a cache stampede). Letting one request refresh the entry while the others wait or use the old value avoids that.

What else shortens the critical path?

  • Set timeouts on every outbound call. One upstream stuck for 30 seconds holds a worker for 30 seconds, and it drags your p99 with it.
  • Return less. If the client shows two fields, do not send forty. Smaller bodies cut serialization and download time.
  • Move work out of the request. Anything the user does not need before the response (sending an email, writing an audit record) can go to a queue.
  • Reuse connections to upstream services and the database instead of opening one per request.

For the wider list of causes and how to recognize each, see 10 common API performance issues and how to detect them.

Workflow with Start branching into API Call A, B and C running in parallel and joining at Finish

How do you confirm the change worked?

Use the same scenario, the same request mix and the same load before and after, and compare p50, p95, p99 and error rate. If the change helped, the tail moved, not just the average. Change one thing per run; if parallelizing and caching ship in one release, you cannot say which one paid off. Then guard the result: put thresholds on p95 and p99 in the pipeline so a slower release fails the build (the LoadFocus GitHub Action and verdict API support this, loadfocus.com/load-testing, read 2026-10-23), and use API monitoring to watch production between tests.

Frequently Asked Questions

How do I reduce API response time without a rewrite?

Measure which dependency dominates a slow endpoint, then run independent calls in parallel, cache slow data that changes rarely, add timeouts, and return smaller responses. These are small code changes compared with a redesign, and each can be checked with a repeat load test.

What is a good API response time?

It depends on the endpoint and what calls it. There is no single target, so set one per endpoint from what the user flow can tolerate, and track p95 and p99 against it. For definitions of the metrics, see what response time is in performance testing.

Is parallelizing API calls always safe?

No. It is safe for independent reads. Calls that depend on each other’s output, or that write data, need to stay ordered, and the upstream service must accept the extra concurrent requests.

Why did my average improve but my p95 did not?

Because a minority of slow requests still dominate the tail. With a cache, for example, the p95 only improves once fewer than 5 percent of requests miss it. Look at the percentiles, not the mean.

Should I load test before or after optimizing?

Both. A baseline test shows where the time goes, and a test with the same scenario after each change shows what the change was worth.

Sources

  • LoadFocus load testing and API monitoring pages (loadfocus.com/load-testing, loadfocus.com/api-monitoring, read 2026-10-23).
  • All timings in the worked examples are invented for illustration and recomputed in this post.

Bogdan

Founder at LoadFocus

Bogdan builds and runs the tools this blog is about. He writes from what the products actually do in production, including the parts that break.

Weekly tips right in your inbox.

Don’t miss out on the latest testing tips and tricks, tools and news related to software testing.

Already +20,000 members in the list.

The Load Testing Platform with AI That Explains Your Results

Load test websites and APIs from 25 cloud regions, monitor page speed and uptime, and get AI analysis that explains your results in plain English.

Cloud load testing, website speed and API monitoring in one place.

Hi there! Can I share a cool thing I'm working on with you?

A software testing newsletter that sparks joy.

Our goal is to create helpful content for software developers and testers.

If you're not into it, you can unsubscribe instantly.