As the cold months roll in, it’s time to make sure your WebSockets are snug and hole-free, just like your favorite pair of winter socks. In this post, I’ll show you how to load-test your socket connections. Nobody wants holes in their SOCKet—keeping things warm, cozy, and performing smoothly, no matter the load!
Table of Contents
- Introduction
- Development Setup
- Load Testing
- Running the Load Test
- Debugging Artillery
- Key Points
- Conclusion
Introduction
Bringing real-time behavior to your solution is not just for the big players anymore—it’s easy to integrate! For this project, the goal was to add real-time updates (both attended and unattended) to a news feed that displays SharePoint Online news.
You can find the complete code for the PuntoBello Realtime News here , and see how to load-test your Azure web app here .
The flow is pretty straightforward. Here’s what we have:
- An SPFx web part
- An Azure web app running a Node.js server
The SPFx web part connects to the Azure web app using the Socket.IO library , an open-source real-time framework for Node.js.
This post focuses on how to set up and load-test your Azure web app so that you can:
- Fine-tune and validate your client- and server-side setup
- Determine the appropriate Azure Service Plans for your workload or organization
Development Setup
Before deploying your web app to Azure, it’s good practice to test locally. Since our web app is essentially a Node.js server and the client code is JavaScript, it’s easy to implement and test locally.
You can find detailed instructions on setting up your environment locally here .
Load Testing
Load testing helps fine-tune our setup and validate parameters such as:
- Client and server configurations (e.g., timeouts)
- The appropriate App Service Plan for simulating production load
Artillery
Artillery
is a powerful load-testing framework for any web stack, including Socket.IO
. You can define your load test in a YAML
file and easily simulate large numbers of clients.
Here’s an example configuration:
config:
target: "{{ $processEnvironment.PUNTOBELLO_TARGET_URL }}" # the URL of your socket.io server in the format wss://your-url.com
phases:
- duration: 1200
arrivalRate: 10
rampTo: 20
name: "Increasing load"
engines:
socketio-v3:
pingInterval: 40000
pingTimeout: 30000
transports: ["websocket"]
scenarios:
- name: Load test PuntoBello PubSub
engine: "socketio-v3"
flow:
- connect:
url: "{{ $processEnvironment.PUNTOBELLO_TARGET_URL }}" # the URL of your socket.io server in the format wss://your-url.com
- think: 600 # Wait for 10 minutes before disconnecting
- disconnect
In this configuration:
- The target and connect URL are set using the environment variable
PUNTOBELLO_TARGET_URL
. - The test runs for 1200 seconds (20 minutes) with an initial arrival rate of 10 clients per second, ramping up to 20 clients per second by the end of the phase.
- Socket.IO parameters like
pingInterval
andpingTimeout
are set. - Each client stays connected for 600 seconds (10 minutes).
The total number of clients during the ramp phase can be calculated as:
Total clients during ramp = (10 + 20) / 2 × 1200 = 15 × 1200 = 18,000 clients
For this load test, you’ll likely need to run a Premium App Service Plan on Azure.
Note: Artillery is a highly flexible framework that allows you to simulate various scenarios and add phases as needed.
Running the Load Test
Assuming the configuration is saved in a file called loadtest.yml
, you can start your test with the following command:
npx artillery run loadtest.yml
Note: You will need to install all dependencies using npm install
and ensure that npx
is available.
When everything runs smoothly, the output in your terminal will look something like this:
Phase started: Increasing load (index: 0, duration: 1200s) 20:39:06(+0200)
--------------------------------------
Metrics for period to: 20:39:10(+0200) (width: 3.443s)
--------------------------------------
vusers.created: ................................................................ 39
vusers.created_by_name.Load test PuntoBello PubSub: ............................ 39
If your server becomes unreachable or overloaded, you’ll see errors like this:
Phase started: Increasing load (index: 0, duration: 1200s) 20:39:06(+0200)
--------------------------------------
Metrics for period to: 20:39:10(+0200) (width: 3.443s)
--------------------------------------
errors.websocket error: ........................................................ 37
vusers.created: ................................................................ 39
vusers.created_by_name.Load test PuntoBello PubSub: ............................ 39
vusers.failed: ................................................................. 37
Debugging Artillery
If things don’t work as expected, you can enable more detailed logs. Artillery supports Node.js-style debugging by prefixing your command with DEBUG
.
To debug Socket.IO:
DEBUG=socketio npx artillery run loadtest.yml
To debug everything:
DEBUG=* npx artillery run loadtest.yml
Key Points
Never Load-Test Against Production
This might seem obvious, but always avoid load-testing your production environment. Load testing can create significant traffic, which might disrupt your normal users.
Every Server Has Its Limit
That’s why we load test—to identify optimal configurations. It’s important to set reasonable load-testing parameters. For example, simulating 100 clients per second equates to 6,000 clients per minute, which is rare in most corporate environments.
Conclusion
Socket.IO makes it easy to integrate real-time functionality into Microsoft 365 solutions. Load-testing your components with Artillery ensures they’re production-ready and able to handle the expected load.