tutorial

How to Monitor k6 Load Testing Infrastructure with Vigilmon

k6 is one of the most popular open-source load testing tools used by developers and SREs to stress-test APIs, services, and web applications. But load testin...

k6 is one of the most popular open-source load testing tools used by developers and SREs to stress-test APIs, services, and web applications. But load testing and uptime monitoring serve different purposes — and using them together gives you a complete picture of your application's reliability.

In this tutorial you'll learn how to set up continuous uptime monitoring with Vigilmon for the services you load test with k6, so you catch both performance regressions during tests and real-world outages between test runs.


Load testing vs. uptime monitoring

These are complementary, not competing, tools:

| Tool | When it runs | What it tells you | |------|-------------|-------------------| | k6 | On-demand or in CI | How your app behaves under synthetic traffic spikes | | Vigilmon | 24/7 continuously | Whether your app is reachable from the real internet right now |

k6 tells you whether your /api/orders endpoint can handle 500 concurrent users. Vigilmon tells you whether /api/orders has been returning 500 errors for the last 3 minutes while you slept. You need both.


What you'll need

  • k6 installed locally or in CI
  • A service to load test (any HTTP API or web app)
  • A free Vigilmon account — sign up in under a minute, no credit card required

Step 1: Add a health endpoint to your service

Before load testing, add a /health route to your application. This gives Vigilmon a lightweight, dependency-verified endpoint to poll continuously — and gives k6 a quick sanity check at the start of every test run.

Node.js / Express:

app.get('/health', async (req, res) => {
  try {
    // Optionally check your DB connection
    await db.query('SELECT 1');
    res.json({ status: 'ok', timestamp: new Date().toISOString() });
  } catch (err) {
    res.status(503).json({ status: 'error', message: err.message });
  }
});

Python / FastAPI:

@app.get("/health")
async def health():
    return {"status": "ok", "timestamp": datetime.utcnow().isoformat()}

Go / Gin:

r.GET("/health", func(c *gin.Context) {
    c.JSON(200, gin.H{"status": "ok"})
})

Make sure the endpoint returns HTTP 200 when healthy and a non-200 status code (503 is conventional) when degraded.


Step 2: Write a k6 load test

Here's a typical k6 script that tests your API under increasing load. Save it as load-test.js:

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

const errorRate = new Rate('errors');

export const options = {
  stages: [
    { duration: '2m', target: 50 },   // ramp up to 50 virtual users
    { duration: '5m', target: 50 },   // hold at 50 VUs
    { duration: '2m', target: 200 },  // spike to 200 VUs
    { duration: '5m', target: 200 },  // hold at 200 VUs
    { duration: '2m', target: 0 },    // ramp down
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'],  // 95th percentile under 500ms
    errors: ['rate<0.01'],             // less than 1% errors
  },
};

const BASE_URL = __ENV.TARGET_URL || 'https://your-api.example.com';

export default function () {
  // Health check
  const health = http.get(`${BASE_URL}/health`);
  check(health, {
    'health is 200': (r) => r.status === 200,
  });

  // Core API endpoints
  const res = http.get(`${BASE_URL}/api/products`, {
    headers: { Authorization: `Bearer ${__ENV.API_TOKEN}` },
  });

  const success = check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 200ms': (r) => r.timings.duration < 200,
  });

  errorRate.add(!success);
  sleep(1);
}

Run the test:

TARGET_URL=https://your-api.example.com k6 run load-test.js

k6 outputs a summary at the end showing percentile latencies, error rates, and whether your thresholds passed. But during the 16-minute test, what's happening to your service from the perspective of real users? That's where Vigilmon comes in.


Step 3: Set up Vigilmon monitors for your tested services

  1. Log in to vigilmon.online and navigate to Monitors → New Monitor
  2. Choose HTTP / HTTPS
  3. Set the URL to your health endpoint: https://your-api.example.com/health
  4. Set check interval to 1 minute
  5. Under Expected response, set status code 200 and optionally body contains "status":"ok"
  6. Save the monitor

Add a second monitor for your main API endpoint:

  1. New Monitor → HTTP / HTTPS
  2. URL: https://your-api.example.com/api/products
  3. Check interval: 1 minute
  4. Expected status: 200
  5. Save

Vigilmon probes these endpoints every minute from multiple locations. If your service goes down — during a load test, during a deploy, or at 3am on a Sunday — you'll know immediately.


Step 4: Run k6 in CI and watch Vigilmon for incidents

When you run k6 in a CI/CD pipeline, it's valuable to correlate the test timeline with your Vigilmon monitor state. If k6 shows a spike in error rates at the same time Vigilmon fires an incident, you know the service actually became unavailable — not just slow.

Here's a GitHub Actions workflow that runs k6 and fails the build on threshold violations:

name: Load Test

on:
  push:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'  # daily at 2am

jobs:
  load-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install k6
        run: |
          sudo gpg -k
          sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg \
            --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
          echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] \
            https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
          sudo apt-get update
          sudo apt-get install k6

      - name: Run load test
        env:
          TARGET_URL: ${{ secrets.STAGING_URL }}
          API_TOKEN: ${{ secrets.API_TOKEN }}
        run: k6 run load-test.js

      - name: Check Vigilmon monitor status
        run: |
          # Optional: query Vigilmon API to verify no incidents during test window
          echo "Check vigilmon.online for incident history"

Step 5: Configure Vigilmon alerts for real-time notification

During and after load tests you want immediate notification if something degrades. Set up alert channels in Vigilmon:

Slack alerts:

  1. Go to Alert Channels → Add Channel → Webhook
  2. Enter your Slack incoming webhook URL
  3. Assign the channel to both your monitors

Email alerts:

  1. Go to Alert Channels → Add Channel → Email
  2. Enter your on-call email address
  3. Enable for both monitors

When a monitor fires, Vigilmon sends:

{
  "monitor_name": "API Health",
  "status": "down",
  "url": "https://your-api.example.com/health",
  "started_at": "2024-07-01T14:23:00Z",
  "duration_seconds": 120
}

This lets you correlate: "k6 ramped to 200 VUs at 14:21, Vigilmon fired at 14:23 — the app collapsed under load."


Step 6: TCP port monitoring for your load test targets

If your service exposes non-HTTP endpoints (Redis, PostgreSQL, gRPC), add TCP port monitors in Vigilmon:

  1. Monitors → New Monitor → TCP Port
  2. Enter your server hostname and port (e.g. your-server.example.com / 6379)
  3. Save

Now you'll detect if the Redis cache that backs your API becomes unreachable mid-test.


Step 7: Create a status page for your tested services

If your API is customer-facing, a status page gives users and stakeholders visibility into uptime:

  1. Status Pages → New Status Page
  2. Name it (e.g. "API Status")
  3. Add your monitors
  4. Publish

Share the URL in your README.md or your developer portal. When k6 reveals a capacity issue that causes an outage, users can check the status page instead of flooding your support queue.


Putting it all together: load testing + monitoring workflow

Here's the complete workflow:

1. Deploy new version to staging
2. Vigilmon confirms /health returns 200 (pre-test sanity check)
3. k6 runs the load test: ramp up → spike → ramp down
4. Vigilmon monitors the endpoint throughout
5. If Vigilmon fires an incident during k6's ramp, you know the load threshold that breaks the service
6. k6 test finishes; check thresholds passed
7. Vigilmon continues monitoring in production 24/7
8. Next k6 run in 24h for regression detection

This means your team always has:

  • k6: synthetic load data on demand, with CI enforcement
  • Vigilmon: real-time availability data, 24/7, from external vantage points

Common patterns with k6 + Vigilmon

Smoke test + monitoring: Run a minimal k6 smoke test (1 VU, 1 minute) in CI just to verify the deploy didn't break anything, while Vigilmon provides continuous coverage between deployments.

Soak testing: Run k6 for 4-8 hours at moderate load. Vigilmon's 1-minute checks will catch memory leaks that cause the service to degrade gradually — before your soak test's error threshold triggers.

Breaking point testing: Ramp k6 to 1000+ VUs. Watch when Vigilmon fires its first incident. That's your breaking point.


What's next

  • Set up k6 Cloud or Grafana k6 for distributed load generation from multiple regions — then correlate with Vigilmon's multi-region uptime data
  • Add heartbeat monitors in Vigilmon if your k6 tests run on a schedule — Vigilmon will alert you if a test job stops running
  • Enable SSL certificate monitoring in Vigilmon for all your test target domains

Get started free at vigilmon.online — monitors go live in under a minute, no credit card required.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →