Back to Blog
n8nK6testingAPIautomation

n8n + K6 Integration: Load Test Your APIs & Workflows

n8nautomation TeamApril 13, 2026
TL;DR: Integrate n8n with K6 to automate load testing of your APIs and n8n workflows. This guide covers setting up K6, triggering tests with n8n, and interpreting results to ensure your automations perform flawlessly under pressure.
Automating load testing with n8n and K6 is a powerful strategy for ensuring the reliability and performance of your APIs and n8n workflows. As your automation projects grow in complexity and criticality, understanding how they behave under various loads becomes essential. This guide will walk you through integrating K6, a modern load testing tool, with n8n to create robust, automated performance testing pipelines.

Why Load Test with n8n and K6?

In today's fast-paced development cycles, automated testing is non-negotiable. While unit and integration tests verify functionality, load testing assesses stability, scalability, and responsiveness under expected (and even extreme) user traffic. Combining n8n with K6 brings several key advantages:

  • Proactive Issue Detection: Identify performance bottlenecks before they impact production users.
  • Scalability Assurance: Verify that your APIs and n8n workflows can handle increased demand.
  • Cost Efficiency: Automate testing saves manual effort and resources.
  • Consistency: Run repeatable tests with consistent configurations.
  • n8n Workflow Validation: Directly load test n8n webhooks or internal endpoints exposed by your n8n instances, especially critical for business-logic heavy workflows.

K6 is an open-source, developer-centric load testing tool that allows you to write tests in JavaScript. Its focus on performance metrics and ease of integration makes it an ideal partner for n8n's flexible automation capabilities.

Setting Up K6 for Performance Testing

Before integrating with n8n, you need a basic K6 setup. K6 can be run locally on your machine or within a containerized environment (like Docker). For this example, we'll assume a local setup.

1. Install K6

Follow the official K6 documentation for installation. For most systems, it's as simple as:

brew install k6 # For macOS
or
apt-get install k6 # For Debian/Ubuntu

2. Write a Simple K6 Test Script

Create a JavaScript file (e.g., test.js) that defines your load test. Here's a basic example that targets an API endpoint:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 10,     // 10 virtual users
  duration: '30s', // for 30 seconds
};

export default function () {
  const res = http.get('https://your-api-endpoint.com/data');
  check(res, { 'status is 200': (r) => r.status === 200 });
  sleep(1);
}

Replace 'https://your-api-endpoint.com/data' with the actual URL you want to test. This could be an external API, a service you've built, or even an activated n8n webhook URL.

3. Run K6 Locally

You can run your K6 script from your terminal:

k6 run test.js

You'll see a summary of the test results, including request durations, error rates, and throughput. This output is what we'll eventually capture and process with n8n.

Triggering K6 Tests with n8n Webhooks

Now, let's connect K6 with n8n. The simplest way to trigger K6 from n8n is to have n8n execute a shell command that runs K6. For this, we'll use n8n's Execute Command node or, more flexibly, a custom HTTP endpoint that runs the K6 command.

Workflow: Triggering K6 via HTTP Request & Shell Command

  1. Webhook Trigger: Start your n8n workflow with a Webhook node. Set the 'Webhook URL' to 'POST' or 'GET' as needed. This will be the trigger for your load test. Copy the URL.

    {
      "body": {
        "test_duration": "1m",
        "virtual_users": 50,
        "target_url": "https://your-app-api.com/v1/users"
      }
    }
    
  2. HTTP Request to a K6 Runner: Since n8n's Execute Command node executes commands on the n8n server itself (which isn't ideal for resource-intensive K6 tests), a better approach is to have a dedicated K6 runner server. This runner exposes an HTTP endpoint that executes K6 tests received via API calls.

    • On your K6 runner server, set up a simple web server (e.g., with Node.js Express or Python Flask) that accepts POST requests.
    • This server receives parameters (like VUs, duration, target URL) from n8n, constructs the K6 command, executes it, and captures the output.

    In n8n, add an HTTP Request node immediately after the Webhook. Configure it to POST to your K6 runner's endpoint, passing the necessary test parameters from the webhook input:

    {
      "method": "POST",
      "url": "http://k6-runner-server:8080/run-k6-test",
      "headers": {
        "Content-Type": "application/json"
      },
      "body": {
        "duration": "{{ $json.body.test_duration }}",
        "vus": {{ $json.body.virtual_users }},
        "target_url": "{{ $json.body.target_url }}"
      }
    }
    
  3. On the K6 Runner Server (example using Node.js/Express):

    
    const express = require('express');
    const { exec } = require('child_process');
    const fs = require('fs');
    const path = require('path');
    
    const app = express();
    app.use(express.json());
    
    app.post('/run-k6-test', (req, res) => {
      const { duration, vus, target_url } = req.body;
    
      if (!duration || !vus || !target_url) {
        return res.status(400).send('Missing duration, vus, or target_url');
      }
    
      const k6ScriptPath = path.join(__dirname, 'dynamic_test.js');
      const k6ScriptContent = `
        import http from 'k6/http';
        import { check, sleep } from 'k6';
    
        export const options = {
          vus: ${vus},
          duration: '${duration}',
        };
    
        export default function () {
          const res = http.get('${target_url}');
          check(res, { 'status is 200': (r) => r.status === 200 });
          sleep(1);
        }
      `;
    
      fs.writeFileSync(k6ScriptPath, k6ScriptContent);
    
      const command = `k6 run --out json=k6_report.json ${k6ScriptPath}`;
    
      exec(command, (error, stdout, stderr) => {
        if (error) {
          console.error(`exec error: ${error}`);
          return res.status(500).json({ error: 'K6 test failed', details: stderr });
        }
        console.log(`stdout: ${stdout}`);
        console.error(`stderr: ${stderr}`); // K6 often outputs summary to stderr
    
        try {
          const report = fs.readFileSync('k6_report.json', 'utf8');
          res.json(JSON.parse(report));
        } catch (readError) {
          console.error(`Error reading K6 report: ${readError}`);
          res.status(500).json({ error: 'Failed to read K6 report', details: readError.message });
        }
      });
    });
    
    const PORT = 8080;
    app.listen(PORT, () => {
      console.log(`K6 Runner listening on port ${PORT}`);
    });
    
    

Tip: For more complex K6 scripts, instead of dynamically writing the script, you can store pre-defined scripts on your K6 runner and pass a script identifier from n8n. The runner then selects and executes the correct script.

Processing K6 Results in n8n

Once K6 finishes its run, it outputs detailed performance metrics. The HTTP Request node in n8n will receive this JSON output from your K6 runner. The next step is to parse and analyze it within n8n.

Workflow: Analyzing K6 Output

  1. HTTP Request (from previous step): This node already contains the JSON output from the K6 runner.

  2. JSON Node: (Optional, if the HTTP Request node didn't automatically parse) Ensure the K6 output is parsed into a usable JSON object. If your runner is sending proper JSON, the HTTP Request node will likely handle this. If it's pure text, use a JSON node to parse {{ $json.data }} (or similar, depending on how your runner returns data).

  3. Set Node / Code Node: Extract the most important metrics. K6's JSON output can be quite verbose. You'll likely want to focus on:

    • http_req_duration (median, average, p90, p95, max)
    • http_req_failed (failure rate)
    • iterations (total requests)
    • vus (virtual users)

    You can use a Code node to simplify the data:

    const k6Result = $json[0].json;
    
    const metrics = {
      duration_median: k6Result.metrics.http_req_duration.values.median,
      duration_p95: k6Result.metrics.http_req_duration.values['p(95)'],
      failed_requests_rate: k6Result.metrics.http_req_failed.values.rate,
      total_requests: k6Result.metrics.iterations.values.count,
      // Add more metrics as needed
    };
    
    return [{ json: metrics }];
    
  4. IF Node: Implement conditional logic based on your performance thresholds. For example, if the failure rate is above 1% or the 95th percentile response time is above 500ms, trigger an alert.

    Condition examples:

    • {{ $json.failed_requests_rate }} is greater than 0.01 (1%)
    • {{ $json.duration_p95 }} is greater than 500
  5. Notification Node (e.g., Slack, Email): If a threshold is exceeded, send a notification to your team. Use expressions to include the specific metrics that failed.

    Example Slack message: Load test failed! P95 Duration: {{ $json.duration_p95 }}ms, Failure Rate: {{ ($json.failed_requests_rate * 100).toFixed(2) }}%

Advanced K6 + n8n Workflows for CI/CD

Taking this integration further, you can embed these load testing workflows directly into your CI/CD pipeline. Imagine automatically running performance tests every time a new version of your API or an n8n workflow is deployed to a staging environment.

Workflow: CI/CD Integration

  1. Webhook Trigger: Your CI/CD pipeline (e.g., GitHub Actions, GitLab CI, Jenkins) makes a POST request to this n8n webhook after a successful deployment to staging.

  2. Execute K6 on Runner (HTTP Request): As described above, trigger your dedicated K6 runner. You can pass the deployed application's URL or specific n8n webhook URLs as parameters.

  3. Process Results (Code Node): Parse the K6 output to extract key metrics.

  4. Database / Google Sheets Node: Store historical performance data in a database (like PostgreSQL or MySQL, which n8n supports with dedicated nodes) or a Google Sheet. This allows for trend analysis over time.

    INSERT INTO k6_test_results (timestamp, target_url, duration_p95, failed_rate)
    VALUES (NOW(), '{{ $json.target_url }}', {{ $json.duration_p95 }}, {{ $json.failed_requests_rate }});
    
  5. IF Node: If performance regressions are detected (e.g., P95 duration is significantly higher than the last stable build), halt the CI/CD pipeline or mark the deployment as failed.

  6. Slack / Email Notification: Alert developers and QA teams about performance degradation.

  7. Response Webhook: Respond to the CI/CD pipeline with a success or failure status code based on test results, allowing the pipeline to proceed or rollback.

Tip: Consider using K6 Cloud for more advanced features like distributed testing and richer analytics, while still triggering and managing tests from n8n via its API.

Deploying Your Testing Workflows

Running these sophisticated performance testing workflows requires a reliable and stable n8n environment. Self-hosting n8n can lead to resource contention when running or monitoring multiple K6 tests, especially if your n8n instances are also executing active production workflows.

For mission-critical testing automation, consider a managed n8n solution from n8nautomation.cloud. With dedicated instances starting at just $15/month, you get:

  • No Server Management: Focus on building workflows, not infrastructure.
  • Automatic Backups: Your testing logic is always safe.
  • Guaranteed Uptime: Your tests run when you need them to, 24/7.
  • Scalability: Your instance scales with your testing needs.

Each instance gives you a unique subdomain, like yourname.n8nautomation.cloud, to keep your testing environments organized and isolated. This ensures that your powerful n8n + K6 testing workflows run smoothly and reliably, providing consistent performance insights without operational overhead.

Ready to automate with n8n?

Get affordable managed n8n hosting with 24/7 support.