PerfLoad / REST API load test
REST API Load Testing: Test Each Verb With Realistic Data
REST endpoints don't all behave the same under load. A read is cheap, a write hits the database, and a delete might fail the second time it runs. This page covers how to test each verb with realistic data, so the numbers you get reflect how your API is actually used.
Load Test Your REST API →Runs in Docker — see the installation guide.
One test per endpoint and verb
A PerfLoad test is built around a single request definition, so the natural pattern is one saved project for each endpoint and verb you care about, such as list orders, create an order, update an order. The runner accepts GET, POST, PUT, PATCH, and DELETE. Name the projects clearly, save them, and rerun them as a set when something changes; comparing a run of the same project before and after a release is where the value is.
Verb by verb
GET: list and read
Reads are where caching matters. Vary the resource so you're not just testing one cached record. A sequential variable of IDs does this:
curl 'https://api.example.com/orders/${orderId}' \
-H 'Authorization: Bearer YOUR_TOKEN'
Define orderId as a Sequential variable with IDs that exist in your test environment. For paginated
lists, do the same with a page variable.
POST: create
Writes create data, and many APIs reject duplicates. Make each request unique with the built-ins
${user}, ${iteration}, ${timestamp}, or ${random}:
curl -X POST 'https://api.example.com/orders' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"reference": "load-${user}-${iteration}", "qty": 1}'
Run this against a test environment: a 30-second run creates real records, and cleaning them up is on you.
PUT and PATCH: update
Updates need an ID that exists. Reuse a sequential list of known IDs, and vary the payload so the write isn't a no-op that the database can skip:
curl -X PATCH 'https://api.example.com/orders/${orderId}' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"note": "updated ${timestamp}"}'
DELETE: remove
A delete only succeeds once per ID. With a Sequential variable, IDs loop back to the start, so a run longer than your ID list will start deleting IDs that are already gone, and those requests will fail. Either supply enough IDs for the whole run, or use a fixed iteration count that matches the list.
Status codes and what counts as failure
PerfLoad checks each response for a 2xx status. That has consequences for REST testing:
- A
404or409your test provokes by design will show as a failure. - A
429means you've hit a rate limit, and your error rate will show it. - For an API that returns 200 with an error object, add a JSON path validation so those responses are caught too.
Auth and headers
Put an Authorization header in the curl command, or use the Workbench's Bearer and Basic auth fields.
Use a token for a test account, and check that it outlasts the test: an expiry in the middle of a run produces a
block of 401 failures that looks like an API problem and isn't.
Putting it in a pipeline
Once each endpoint has a saved run, the run IDs become baselines. A pipeline can fetch each one, override the users or duration, and read p95 from the summary; see CI/CD load testing for the script.
FAQ
Do I need a separate test environment?
For anything that writes or deletes, yes. Load tests generate real requests, and a POST or DELETE test changes real data in whatever it points at.
How do I test an endpoint that needs an ID from another call?
Prepare a list of valid IDs and feed them in as a Sequential or Random variable. That keeps each test a single request while still using realistic identifiers.
How many users should a REST test start with?
Start with a few users and a short duration, check the failures, then scale. Write endpoints usually hit their limits well before read endpoints do.
Related guides
Test every verb your API exposes
Save a project for each endpoint, then rerun them whenever something changes.
Load Test Your REST API →