Load testing is one of the most important kinds of testing in the software application lifecycle. With load tests, you can subject your application to the type of pressures expected in production. That gives you the information to fine-tune infrastructure and architectures, making sure that your application does not dip below your 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 a decline in performance. 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 there is 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 implement load testing on 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:
- Basic knowledge of JavaScript
- Node.js installed on your system (version >= 18)
- A Heroku account
- A CircleCI account
- A GitHub account
Our tutorials are platform-agnostic, but use CircleCI as an example. If you don’t have a CircleCI account, sign up for a free one here.
Setting up Heroku for 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.
Take note of the app name (node-load-tests
here) 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 project
For the next step, you will need to clone the API project. The API project 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 --single-branch --branch base-project 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 a default port of 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.
Result? The API seems to be working fine.
Adding configuration file
In this step, you will configure the CI/CD pipeline that will automatically deploy your application to Heroku. This script also load tests the API’s /users/get
endpoint each time a deployment is made. 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 https://<HEROKU_APP_NAME>-<RANDOM_NUMBER>.herokuapp.com/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 send250
requests to the/users/get
endpoint using a concurrency of20
and aKeep-Alive
connection type for a persistent connection with the-k
flag.
Using workflows, 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 https://<HEROKU_APP_NAME>-<RANDOM_NUMBER>.herokuapp.com
with your Heroku app URL.
Time to run the load test pipeline. Commit all changes to the project and push to your remote GitHub repository. This will automatically trigger the pipeline and you should have a successful build.
Your next task is to get a project set up 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.
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 eithernode-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.
Click the loadtestapi
job in the workflow to review the results of the load test.
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 by you or by your organization. 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 customer are performing critical work, or important fun.
In this tutorial, you have learned to deploy an API and immediately run a load test to verify its capability 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.
Happy coding!
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.