Guides

API load testing

What to test, how to test it and what to think about when load testing or stress testing your REST API application.

Overview

Testing a modern REST API is very similar to testing a web application. You want to ensure that all the dependencies of the system are put under load as well - the "heaviest" workloads. By examples these can include:

  • Authentication and user management
  • CRUD operations, especially Updates or Creates
  • High speed read operations

These operations are interactive, dynamic content - and often POST requests. They typically are generated by a language like PHP, and often require a SQL database interaction. These are the common bottlenecks in a modern web application. Server load testing is very different, and has to do with raw requests per second from the web server itself, e.g. Nginx, Apache, etc.

Breaking your API into common tasks

We want to split load testing for APIs into the three categories above, and potentially more depending on the size and load profile of your API. For example, you might know your API handles very few write operations but a large number of read operations. Another example comparison would be do you have API clients that are sending a large number of requests, or, a large number of clients with fewer requests. For this example, we'll define our API like this:

  • High volume of dynamic read operations
  • Low volume of write operations
  • Large number of different users

We're going to initially read two test variables from that. Firstly, we'll set our wait time on each individual API user to 1 request per 1-3 seconds. Secondly, we'll set our number of connected API clients (users) to 5000 initially.

The last piece of information from our tasks is that we know we are going to get far more read operations, so we'll plan for around 10x as many reads per client as there are writes.

Creating our API test

As you can see above, we have set up the basic layout of our test. The next step will be to define the actual test locustfile - the script that is going to generate our requests to our API.

Creating a the locustfile

We can now write our LoadForge test, which we will execute against our website we've defined above. We'll start by defining just the basics - the website to run it against, and that we'll start with 5000 simultaneous users. Remember that with our 1-3 seconds wait time decision that will be a large number of users.

from locust import HttpLocust, TaskSet, task
import random
from random import randint

class ApiLoadTest(TaskSet):
    wait_time = between(1, 3)

    @task(10)
    def get_item(self):
        value = randint(0, 1000)
        self.client.get("/api/item?id=%value" % value, name="/api/item?id=[id]")

    @task(1)
    def create_item(self):
        response = self.client.request(method="POST",
            url="/api/item",
            headers={
                "Authorization": 'Token YOUR_BEARER_TOKEN_EXAMPLE'
            },
            data={
                "itemName": "Test Item",
                "itemPrice": "1999",
            })

Lets break this down, it's quite similar to our default template, and if you want advanced uses check out our documentation.

We've defined a low wait time as discussed, and also set get_itemm to run 10 times as much as create_item. We're fetching a random id on the get (customize this to be something real), and on the post we're making an item.

Over time you'll build a far broader API test, testing each function and being able to profile the performance of each request. That's right: LoadForge will show you the response time and RPS for each item defined in your test, helping to find slow queries!

Understanding results

Interpreting the results of your test are as important as running the test, if not more. Continue this on our reading load test results guide.

Ready to run your test?
Start your first test within minutes.