DEV Community

Cover image for Stress Testing in node.js πŸ§ͺ
Ali nazari
Ali nazari

Posted on

16 2 1 1 1

Stress Testing in node.js πŸ§ͺ

Stress testing is a form of performance testing where the application is pushed beyond its normal operational capacity.

The goal is to determine the application’s robustness, to identify breaking points, and to ensure that the system gracefully handles or recovers from heavy loads.

developers design these tests to simulate real-world scenariosβ€”sometimes focusing on extreme usage conditions (often in a staging environment) to ensure reliability when deployed.

wearing glasses


Folder Structure for Stress Testing

While folder structures can vary from one team to another, developers often follow these conventions to keep their project organized:

  • Separate Test Folders:

Developers usually keep stress tests separate from unit tests and integration tests. A common approach is to create a dedicated folder:

β”œβ”€β”€ test/
β”‚   β”œβ”€β”€ unit/
β”‚   β”œβ”€β”€ integration/
β”‚   └── stress/
β”‚       β”œβ”€β”€ scenarios/
β”‚       β”‚   β”œβ”€β”€ highConcurrency.js
β”‚       β”‚   └── longDuration.js
β”‚       β”œβ”€β”€ config/
β”‚       β”‚   └── artillery-config.yml
β”‚       └── helpers/
β”‚           └── loadGenerator.js
Enter fullscreen mode Exit fullscreen mode
  • Scenarios Folder:

Under the stress directory, you will often find a scenarios or cases folder where each file represents a different load scenarioβ€”this could be a test for high concurrency, prolonged load, or burst traffic.

  • Config Folder:

A folder for configuration files (e.g., YAML or JSON) is common.

Tools like Artillery or k6 use these configuration files to define the parameters of the test (such as the number of virtual users, duration, endpoints, etc.).

  • Helpers Folder:

You might include helper scripts or libraries that assist in running the tests or processing the output data.


Best Practices and Considerations

1. Define Clear Objectives:

Define what β€œstress” means for your application.

Determine ** key performance indicators** (KPIs) like response times, throughput, error rates, and system resource usage.

Know the normal performance metrics so you can detect anomalies when under stress. (Establish Baselines)

2. Test Environment Setup:

Always run stress tests in an environment similar to production but isolated, so that testing does not affect real users.

Use data and configurations that mirror your production environment as closely as possible to identify realistic bottlenecks.

3. Incremental Testing:

Begin with a lower load and gradually increase it to pinpoint the exact threshold where your application starts to degrade.

Use monitoring and logging tools (e.g., New Relic, Datadog) to observe system behavior during testing. This will help you understand resource usage and failure points.

4. Consider External Factors:

Account for network latencies, especially if your Node.js application communicates with external services.

Evaluate your load balancers, caching strategies, and database performance as these components also affect overall system performance.


stress test scenarios

Below is a list of common stress test scenarios that developers typically design and run.

Each scenario focuses on a different aspect of application behavior under extreme load, ensuring a comprehensive evaluation of the system.

1.High Concurrency Test

Simulate a large number of simultaneous users or connections.

Focus: Assess how the application handles many parallel requests and identify bottlenecks in processing or resource management.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 60      # Duration in seconds
      arrivalRate: 100  # 100 new virtual users per second
scenarios:
  - flow:
      - get:
          url: "/api/endpoint"
Enter fullscreen mode Exit fullscreen mode

2.Sustained Load (Prolonged Load) Test

Run the application under a steady load for an extended period (e.g., several minutes to hours).

Focus: Detect memory leaks, gradual degradation in performance, and stability issues over time.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 600   # 10 minutes duration
      arrivalRate: 20 # Steady rate of 20 users per second
scenarios:
  - flow:
      - get:
          url: "/api/endpoint"
Enter fullscreen mode Exit fullscreen mode

3.Burst Traffic (Spike) Test

Simulate sudden increases in traffic in short bursts.

Focus: Evaluate the application’s ability to handle unexpected spikes and its capability to recover when the traffic subsides.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 10      # Normal load phase
      arrivalRate: 50
    - duration: 5       # Burst phase
      arrivalRate: 200
    - duration: 10      # Post-burst cooldown
      arrivalRate: 50
scenarios:
  - flow:
      - get:
          url: "/api/endpoint"
Enter fullscreen mode Exit fullscreen mode

4.Resource Exhaustion Test

Push system resources (such as CPU, memory, disk I/O) to their limits.

Focus: Identify when and how resource saturation occurs,and verify that appropriate safeguards (like rate limiting or backpressure) are in place.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 60
      arrivalRate: 10
    - duration: 60
      arrivalRate: 50
    - duration: 60
      arrivalRate: 100
scenarios:
  - flow:
      - get:
          url: "/api/endpoint"
Enter fullscreen mode Exit fullscreen mode

tired lady

You made it this far πŸ˜ƒ. Now dig deep and finish strong!

5.Connection Flood Test

Open a very high number of connections rapidly to stress the network and server limits.

Focus: Understand how the application and its infrastructure deal with numerous open sockets and potential connection timeouts or errors.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 30
      arrivalRate: 500  # Very high arrival rate to flood with connections
scenarios:
  - flow:
      - get:
          url: "/api/endpoint"
Enter fullscreen mode Exit fullscreen mode

6.Slow Request (Slowloris) Test

Send requests very slowly to keep connections open without completing them.

Focus: Determine how the server manages idle connections and whether it implements proper timeout and resource recovery mechanisms.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 60
      arrivalRate: 10
scenarios:
  - flow:
      - function: "sendSlowRequest"
functions:
  sendSlowRequest: |
    function(userContext, events, done) {
      const http = require('http');
      const options = {
        hostname: 'localhost',
        port: 3000,
        path: '/api/slow-endpoint',
        method: 'GET'
      };
      const req = http.request(options, (res) => {
        res.on('data', () => {});
        res.on('end', () => { done(); });
      });
      req.on('error', (e) => { done(e); });
      // Simulate slow sending of request: write partial data then wait before finishing the request
      req.write('partialData');
      setTimeout(() => {
        req.end();
      }, 10000); // Delay of 10 seconds before completing the request
    }
Enter fullscreen mode Exit fullscreen mode

7.Error Handling and Recovery Test

Intentionally trigger errors or service failures during stress.

Focus: Test how gracefully the application degrades, how errors are logged, and whether recovery mechanisms (like retry logic or circuit breakers) kick in effectively.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 60
      arrivalRate: 20
scenarios:
  - flow:
      - get:
          url: "/api/error"  # This endpoint should simulate errors
Enter fullscreen mode Exit fullscreen mode

8.Dependency Under Load Test

Simulate high load on external dependencies (such as databases, cache systems, or third-party APIs).

Focus: Determine the impact on your Node.js application when underlying services are slow or unavailable, ensuring the application handles such scenarios gracefully.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 60
      arrivalRate: 50
scenarios:
  - flow:
      - get:
          url: "/api/dependency-endpoint"
Enter fullscreen mode Exit fullscreen mode

9.Simulated Distributed Denial of Service (DDoS) Scenario

Mimic a DDoS attack by overwhelming the system with a flood of requests from multiple sources.

Focus: Evaluate the effectiveness of security measures, rate limiting, and traffic filtering under an extreme flood of network requests.

config:
  target: "http://localhost:3000"
  phases:
    - duration: 30
      arrivalRate: 1000  # Extreme load
scenarios:
  - flow:
      - get:
          url: "/api/endpoint"
Enter fullscreen mode Exit fullscreen mode

Common Tools Used for Stress Testing in Node.js

Artillery

Artillery is popular for its simple YAML configuration files which define load scenarios and integrates well with Node.js applications.

k6

The scripts are written in JavaScript which makes it familiar for Node.js developers. The tests can be automated as part of your CI/CD pipeline.

autocannon

It’s often used for quick benchmarks and stress testing, especially when you need to focus on the performance of a single endpoint or a small set of endpoints

Loadtest

The module can be executed as part of your test suite, though it might not be as robust for very large-scale testing as some other tools.


happy boss

This is your boss after you read this article.πŸ‘† lol


other posts:


Let's connect!!: 🀝

LinkedIn
GitHub

Quickstart image

Django MongoDB Backend Quickstart! A Step-by-Step Tutorial

Get up and running with the new Django MongoDB Backend Python library! This tutorial covers creating a Django application, connecting it to MongoDB Atlas, performing CRUD operations, and configuring the Django admin for MongoDB.

Watch full video β†’

Top comments (1)

Collapse
 
silentwatcher_95 profile image
Ali nazari β€’

The examples I used are from the Artillery tool.

Neon image

Next.js applications: Set up a Neon project in seconds

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Get started β†’

πŸ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay