In most cases, when users start to access and use a new application or a new release, app performs pretty well. As the user base grows and usage increases, the app can outgrow its infrastructure. Users can start experiencing a dip in performance. Latency increases, bandwidth and memory get exhausted quickly, and some code architectures start to fail because they do not scale well with the increased amount of users. 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 especially in financial terms.
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 this tutorial, we will be load testing a simple Node.js API using Apache benchmark, a load testing and benchmarking tool for HTTP servers.
Prerequisites
To follow this tutorial, a few things are required:
- Basic knowledge of Javascript
- Node.js installed on your system (version >= 10.3)
- A Heroku account
- A CircleCI account
- A GitHub account
With all these installed and set up, we can begin the tutorial.
Setting up Heroku for hosting
The first step is to set up a Heroku application to host our API. Navigate to your Heroku apps dashboard. Click New, then Create new app. Using the name you prefer, create a new app.
Take note of the app name (node-loadtest
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 this 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/coderonfleek/node-loadtest
Once the cloning process is complete, go into the root of the project and install the dependencies by running these commands:
cd node-loadtest
npm install
When the installation is complete, run the application with the command:
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. This should return an array of users.
Result? The API seems to be working fine.
Connecting to CircleCI
To set up the API project on CircleCI, you first need to push the project to GitHub.
Next, go to the Projects page on the CircleCI dashboard (Select the appropriate GitHub account) to add the project.
Click the Set Up Project button to begin. This will load the next screen.
On the setup page, click Use Existing Config to instruct CircleCI that we are adding a configuration file manually and not using the sample displayed. Next, you will be prompted to either download a configuration file for the pipeline or to start building.
Click Start Building. This build will fail because we have not set up our configuration file yet. We will complete this step later on.
The final thing we need to do on the CircleCI console is to set up environment variables for the project we just added. This will enable our project to have authenticated access to our Heroku application for deployments.
Go to your project’s settings by clicking the Project Settings button on the Pipelines page. Make sure your project is the currently selected project.
On the Project Settings page, click Environment Variables (it is in the side menu).
On the Environment Variables page, click Add Environment Variable.
Add the following environment variables:
HEROKU_APP_NAME
is the name of your Heroku application (in this casecci-node-loadtest
)HEROKU_API_KEY
is your Heroku account API key (mentioned earlier).
You now have everything set up on your CircleCI console for deployment to Heroku.
Adding the load test in the pipeline configuration
It is now time to build the deployment pipeline that will load test 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:
jobs:
build:
executor: heroku/default
steps:
- checkout
- heroku/install
- heroku/deploy-via-git
loadtestapi:
docker:
- image: circleci/node:10.16.3
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.herokuapp.com/users/get
orbs:
heroku: circleci/heroku@0.0.10
version: 2.1
workflows:
deploy:
jobs:
- build
- loadtestapi:
requires:
- build
In the configuration you just created, there are two jobs:
-
The
build
job uses CircleCI’s Heroku orb to deploy the API project from the GitHub repository to the Heroku app created on the hosting platform -
Once the API is deployed, the
loadtestapi
installs the Apache benchmark tool then uses the tool 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 loadtestapi
job will not run until the build
job is complete, ensuring that we do not run the load test until the API is successfully deployed.
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.
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.44
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 details are shown that detail how the tests ran. These details can be useful in tuning your application architecture to better scale for thousands to millions of users using the 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 downtime while users make use of the application. In this tutorial, we have been able 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 Apache benchmark. There are also specialized tools that can be plugged into the process or used as a replacement for Apache benchmark, like 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.