Load testing is an integral part of the software application lifecycle, especially when it comes to ensuring the reliability and performance of your APIs. API load tests subject your application to production-like pressures to make sure that your app does not dip below performance thresholds.

In most cases, new applications perform pretty well. But as the user base grows and usage increases, an app can outgrow its infrastructure. Users can start experiencing performance issues. Latency increases and bandwidth and memory get exhausted quickly. Some code architectures start to fail because they do not scale well with the increased amount of user activity.

This is not an unexpected issue; infrastructure and application architecture are meant to scale with increased usage. The risk is not knowing ahead of time when the application will break or when the infrastructure will go down because of increased load on the server. This issue can lead to big losses, in both financial terms and customer confidence.

In this tutorial, you will learn how to load test a simple Node.js API using ApacheBench (ab), a load testing and benchmarking tool for HTTP servers. You will use a CircleCI continuous integration and continuous deployment (CI/CD) pipeline to automatically deploy and load test updates to your API.

Prerequisites

To follow this tutorial, a few things are required:

  1. Basic knowledge of JavaScript
  2. Node.js installed on your system (version >= 18)
  3. A Heroku account
  4. A CircleCI account
  5. A GitHub account

Setting up Heroku for API hosting

The first step is to set up a Heroku application to host your API. Go to your Heroku apps dashboard. Click New, then Create new app. Decide on a name, then create the new app. If you haven’t already uploaded a payment method, you’ll need to do so here.

New app - Heroku

Take note of the app name (node-load-tests in this example) you just entered. You will need this later on during the tutorial.

Next, locate your Heroku API Key in the Account Settings section of your dashboard.

You will also need to copy your API Key from this page later in the tutorial.

Cloning the test API

For the next step, you will need to clone the API project. The API you are using for this example is a simple Node.js API application with a root endpoint and another endpoint for fetching a collection of users. Clone the project by running this command:

git clone https://github.com/CIRCLECI-GWP/load-tests-node-apis.git

Once the cloning process is complete, go into the root of the project and install the dependencies:

cd load-tests-node-apis
npm install

When the installation is complete, run the application:

npm start

The application will start listening on port 3000. Open up Postman and make a GET request to the http://localhost:3000/users/get endpoint or check that link using your favorite browser. This should return an array of users.

Get users - browser

Configuring an API load testing pipeline

In this next step, you will configure a CI/CD pipeline that will automatically deploy your application to Heroku and load test the API’s /users/get endpoint every time you make a change to your application code.

At the root of your project, create a folder named .circleci and a file named config.yml within it. Inside config.yml, enter this code:

version: 2.1

orbs:
  node: circleci/node@5.1.1
jobs:
  build-and-deploy:
    docker:
      - image: "cimg/base:stable"
    steps:
      - checkout
      - node/install
      - run:
          command: npm install
          name: Install dependencies
      - run:
          name: Deploy app to Heroku
          command: |
            git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git main

  load-test-api:
    docker:
      - image: "cimg/base:stable"
    steps:
      - run:
          name: Run Load Test
          command: |
            sudo apt-get update
            sudo apt-get install apache2-utils
            ab -k -c 20 -n 250 your-heroku-app-url/users/get

workflows:
  deploy:
    jobs:
      - build-and-deploy
      - load-test-api:
          requires:
            - build-and-deploy

In the configuration you just created, there are two jobs:

  • The build-and-deploy job uses Git to deploy the API project from the GitHub repository to the Heroku app created on the hosting platform.
  • Once the API is deployed, the load-test-api job installs the ApacheBench tool then uses it to send 250 requests to the /users/get endpoint using a concurrency of 20 and a Keep-Alive connection type for a persistent connection with the -k flag.

Because you structured the worklow to make the load-test-api step dependent on the build-and-deploy step, the load-test-api job will not run until the build-and-deploy job is complete. This ensures that you do not run the load test until the API is successfully deployed.

Note: Replace your-heroku-app-url with your Heroku app URL. This can be found in the “Domains” section of the app settings.

Setting up API load testing on CircleCI

Now that you’ve configured your pipeline, your next task is to set it up as a project on CircleCI. Begin by pushing your project to GitHub.

Next, log into your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard.

Click Set Up Project next to your load-tests-node-apis project.

Select project

You will be prompted to enter the name of the branch your configuration file is on. Click Set Up Project once you are done. This will trigger your first workflow, which will fail.

The deployment process fails because you have not provided your Heroku API key. To fix that, click the Project Settings button, then click Environment Variables. Add these two new variables:

  • For HEROKU_APP_NAME, add the app name you used in Heroku. The name will be either node-load-tests or a custom name if you created one.
  • For HEROKU_API_KEY enter the Heroku API key that you retrieved earlier from the account settings page.

Re-run your workflow from the start, and this time your workflow will run successfully.

Build successful - CircleCI

Click the loadtestapi job in the workflow to review the results of the load test.

Build details - CircleCI

The results show that all 250 requests were served within 0.165 seconds. Whether this is a good result or not depends on the performance metrics set for your application. Other data is shown that details how the tests ran. These details can be useful in tuning your application architecture to better scale for thousands to millions of users on your application.

Conclusion

Any enterprise or startup organization serving software to users should take load tests seriously. Load testing enables you to avoid the consequences of user downtime while customers are engaged in critical work or important fun.

In this tutorial, you have learned to deploy an API and immediately run a load test to verify its ability to handle web traffic. There are many ways to extend these load tests using ApacheBench. There are also specialized tools that can be plugged into the process or used as a replacement for ApacheBench, like k6. For an example, check out API performance testing with k6.


Fikayo Adepoju is a LinkedIn Learning (Lynda.com) Author, Full-stack developer, technical writer, and tech content creator proficient in Web and Mobile technologies and DevOps with over 10 years experience developing scalable distributed applications. With over 40 articles written for CircleCI, Twilio, Auth0, and The New Stack blogs, and also on his personal Medium page, he loves to share his knowledge to as many developers as would benefit from it. You can also check out his video courses on Udemy.

Read more posts by Fikayo Adepoju