Skip to content
Back to skills

Load Testing

ASecurity

Auto-activates when user mentions load test, performance test, stress test, k6, Artillery, benchmark, or scalability testing. Expert in designing and executing performance tests.

  • 666 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 9, 2026
developmentjavascripttypescriptgojavabashnodetestinggitapici/cd

Works with

  • api

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill load-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Load Testing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Load Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-load-testing/badge)](https://www.skillsdirectory.com/skills/majiayu000-load-testing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: load-testing
description: Auto-activates when user mentions load test, performance test, stress test, k6, Artillery, benchmark, or scalability testing. Expert in designing and executing performance tests.
category: testing
---

# Load Testing & Performance Testing

Creates comprehensive load tests using k6, Artillery, and other tools to validate application performance under stress.

## When This Activates

- User says: "load test this", "performance test", "stress test", "benchmark"
- User mentions: "k6", "Artillery", "JMeter", "Gatling", "scalability"
- Performance validation needed
- Pre-production testing
- Capacity planning questions

## Load Testing Tools Comparison

### k6 (Recommended)
- **Best for:** Modern apps, APIs, microservices
- **Language:** JavaScript/TypeScript
- **Pros:** Cloud-native, great metrics, scriptable
- **Use when:** Testing REST APIs, GraphQL, WebSocket

### Artillery
- **Best for:** Quick tests, CI/CD integration
- **Language:** YAML + JavaScript
- **Pros:** Simple config, plugins, HTTP/WS/Socket.io
- **Use when:** Simple scenarios, rapid testing

### Apache JMeter
- **Best for:** Enterprise apps, complex scenarios
- **Language:** GUI-based + Java
- **Pros:** Mature, extensive protocols, GUI
- **Use when:** Legacy systems, complex workflows

## k6 Load Testing

### Basic Load Test

```javascript
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend, Counter } from 'k6/metrics';

// Custom metrics
const errorRate = new Rate('errors');
const checkDuration = new Trend('check_duration');
const requests = new Counter('requests');

// Test configuration
export const options = {
  stages: [
    { duration: '2m', target: 10 },   // Ramp up to 10 users
    { duration: '5m', target: 10 },   // Stay at 10 users
    { duration: '2m', target: 50 },   // Ramp up to 50 users
    { duration: '5m', target: 50 },   // Stay at 50 users
    { duration: '2m', target: 100 },  // Ramp up to 100 users
    { duration: '5m', target: 100 },  // Stay at 100 users
    { duration: '2m', target: 0 },    // Ramp down
  ],
  thresholds: {
    http_req_duration: ['p(95)<500', 'p(99)<1000'], // 95% < 500ms, 99% < 1s
    http_req_failed: ['rate<0.01'],                  // Error rate < 1%
    errors: ['rate<0.1'],                            // Custom error rate < 10%
  },
};

const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000';
const API_TOKEN = __ENV.API_TOKEN || '';

export default function () {
  const params = {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_TOKEN}`,
    },
    tags: { name: 'GetUsers' },
  };

  // GET request
  let response = http.get(`${BASE_URL}/api/users`, params);
  
  const checkResult = check(response, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
    'has users': (r) => JSON.parse(r.body).data.length > 0,
  });

  errorRate.add(!checkResult);
  checkDuration.add(response.timings.duration);
  requests.add(1);

  // POST request
  const payload = JSON.stringify({
    name: 'Test User',
    email: `test-${Date.now()}@example.com`,
  });

  response = http.post(`${BASE_URL}/api/users`, payload, params);
  
  check(response, {
    'user created': (r) => r.status === 201,
  });

  sleep(1); // Think time between requests
}

export function handleSummary(data) {
  return {
    'summary.json': JSON.stringify(data),
    stdout: textSummary(data, { indent: ' ', enableColors: true }),
  };
}
```

### Advanced Scenarios

```javascript
// advanced-test.js
import http from 'k6/http';
import { check, group, sleep } from 'k6';
import { SharedArray } from 'k6/data';
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';

// Load test data
const users = new SharedArray('users', function () {
  return papaparse.parse(open('./users.csv'), { header: true }).data;
});

export const options = {
  scenarios: {
    // Scenario 1: Constant load
    constant_load: {
      executor: 'constant-vus',
      vus: 50,
      duration: '5m',
    },
    // Scenario 2: Ramping load
    ramping_load: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '5m', target: 100 },
        { duration: '10m', target: 100 },
        { duration: '5m', target: 0 },
      ],
      gracefulRampDown: '30s',
    },
    // Scenario 3: Stress test
    stress_test: {
      executor: 'ramping-arrival-rate',
      startRate: 50,
      timeUnit: '1s',
      preAllocatedVUs: 500,
      maxVUs: 1000,
      stages: [
        { duration: '2m', target: 100 },
        { duration: '5m', target: 200 },
        { duration: '2m', target: 500 },
        { duration: '5m', target: 500 },
        { duration: '2m', target: 0 },
      ],
    },
  },
};

export default function () {
  const user = users[Math.floor(Math.random() * users.length)];

  group('User Flow', function () {
    // 1. Login
    group('Login', function () {
      const loginRes = http.post(`${BASE_URL}/api/auth/login`, JSON.stringify({
        email: user.email,
        password: user.password,
      }), {
        headers: { 'Content-Type': 'application/json' },
      });

      check(loginRes, {
        'login successful': (r) => r.status === 200,
      });

      const token = loginRes.json('token');
      
      // 2. Get profile
      group('Get Profile', function () {
        const profileRes = http.get(`${BASE_URL}/api/profile`, {
          headers: {
            'Authorization': `Bearer ${token}`,
          },
        });

        check(profileRes, {
          'profile loaded': (r) => r.status === 200,
        });
      });

      // 3. Create post
      group('Create Post', function () {
        const postRes = http.post(`${BASE_URL}/api/posts`, JSON.stringify({
          title: 'Load Test Post',
          content: 'This is a test post from k6',
        }), {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`,
          },
        });

        check(postRes, {
          'post created': (r) => r.status === 201,
        });
      });
    });
  });

  sleep(Math.random() * 3 + 2); // Random think time 2-5s
}
```

### GraphQL Load Test

```javascript
// graphql-test.js
import http from 'k6/http';
import { check } from 'k6';

export const options = {
  vus: 50,
  duration: '5m',
  thresholds: {
    http_req_duration: ['p(95)<1000'],
  },
};

const GRAPHQL_ENDPOINT = `${__ENV.BASE_URL}/graphql`;

export default function () {
  const query = `
    query GetPosts($first: Int!) {
      posts(first: $first) {
        edges {
          node {
            id
            title
            author {
              name
            }
          }
        }
      }
    }
  `;

  const variables = { first: 20 };

  const response = http.post(
    GRAPHQL_ENDPOINT,
    JSON.stringify({ query, variables }),
    {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${__ENV.API_TOKEN}`,
      },
    }
  );

  check(response, {
    'no errors': (r) => !r.json('errors'),
    'has data': (r) => r.json('data.posts.edges.length') > 0,
  });
}
```

## Artillery Load Testing

### Basic Configuration

```yaml
# artillery.yml
config:
  target: "http://localhost:3000"
  phases:
    - duration: 60
      arrivalRate: 10     # 10 users per second
      name: "Warm up"
    - duration: 300
      arrivalRate: 50     # 50 users per second
      name: "Sustained load"
    - duration: 120
      arrivalRate: 100    # 100 users per second
      name: "Spike"
  
  processor: "./helpers.js"
  
  variables:
    apiToken: "{{ $processEnvironment.API_TOKEN }}"
  
  plugins:
    expect: {}
    metrics-by-endpoint: {}

scenarios:
  - name: "User Registration and Login"
    flow:
      - post:
          url: "/api/auth/register"
          json:
            email: "user-{{ $randomString() }}@example.com"
            name: "Test User"
            password: "password123"
          capture:
            - json: "$.token"
              as: "authToken"
          expect:
            - statusCode: 201
            - contentType: json
            - hasProperty: token

      - get:
          url: "/api/profile"
          headers:
            Authorization: "Bearer {{ authToken }}"
          expect:
            - statusCode: 200

      - post:
          url: "/api/posts"
          headers:
            Authorization: "Bearer {{ authToken }}"
          json:
            title: "Test Post"
            content: "This is a test"
          expect:
            - statusCode: 201

  - name: "Browse Posts"
    weight: 3
    flow:
      - get:
          url: "/api/posts?page=1&limit=20"
          expect:
            - statusCode: 200
            - hasProperty: data

      - think: 2  # Wait 2 seconds

      - get:
          url: "/api/posts/{{ $randomNumber(1, 100) }}"
          expect:
            - statusCode: [200, 404]
```

```javascript
// helpers.js
module.exports = {
  generateRandomEmail,
  logResponse,
};

function generateRandomEmail(context, events, done) {
  context.vars.email = `user-${Date.now()}@example.com`;
  return done();
}

function logResponse(requestParams, response, context, ee, next) {
  if (response.statusCode >= 400) {
    console.error(`Error ${response.statusCode}: ${response.body}`);
  }
  return next();
}
```

## Running Tests

```bash
# k6
k6 run load-test.js
k6 run --vus 100 --duration 5m load-test.js
k6 run --env BASE_URL=https://api.example.com load-test.js

# k6 Cloud
k6 cloud load-test.js

# Artillery
artillery run artillery.yml
artillery run --target https://api.example.com artillery.yml

# Artillery with environment
API_TOKEN=xxx artillery run artillery.yml

# Generate HTML report
artillery run --output report.json artillery.yml
artillery report report.json
```

## CI/CD Integration

### GitHub Actions

```yaml
# .github/workflows/load-test.yml
name: Load Test

on:
  schedule:
    - cron: '0 2 * * *'  # Run daily at 2 AM
  workflow_dispatch:

jobs:
  load-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Run k6 load test
        uses: grafana/k6-action@v0.3.0
        with:
          filename: tests/load-test.js
          cloud: true
          token: ${{ secrets.K6_CLOUD_TOKEN }}
        env:
          BASE_URL: ${{ secrets.STAGING_URL }}
          API_TOKEN: ${{ secrets.API_TOKEN }}
      
      - name: Upload results
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: load-test-results
          path: summary.json
```

## Performance Benchmarking

```javascript
// benchmark.js
import http from 'k6/http';
import { check } from 'k6';

export const options = {
  scenarios: {
    baseline: {
      executor: 'constant-vus',
      vus: 1,
      duration: '1m',
      tags: { test_type: 'baseline' },
    },
  },
};

export default function () {
  const endpoints = [
    '/api/users',
    '/api/posts',
    '/api/comments',
  ];

  endpoints.forEach(endpoint => {
    const response = http.get(`${BASE_URL}${endpoint}`);
    
    check(response, {
      [`${endpoint} status 200`]: (r) => r.status === 200,
    });
  });
}

export function handleSummary(data) {
  const baseline = {
    endpoints: {},
    timestamp: new Date().toISOString(),
  };

  for (const [name, metric] of Object.entries(data.metrics)) {
    if (name.includes('http_req_duration')) {
      baseline.endpoints[name] = {
        avg: metric.values.avg,
        p95: metric.values['p(95)'],
        p99: metric.values['p(99)'],
      };
    }
  }

  return {
    'baseline.json': JSON.stringify(baseline, null, 2),
  };
}
```

## Analyzing Results

### Key Metrics to Monitor

1. **Response Time**
   - Average, p95, p99
   - Target: p95 < 500ms, p99 < 1s

2. **Error Rate**
   - HTTP 4xx, 5xx errors
   - Target: < 1%

3. **Throughput**
   - Requests per second
   - Target: Based on requirements

4. **Concurrent Users**
   - Maximum sustainable load
   - Target: Based on traffic projections

### Identifying Bottlenecks

```javascript
// Find slow endpoints
const slowRequests = data.metrics.http_req_duration.values;
console.log(`Average: ${slowRequests.avg}ms`);
console.log(`p95: ${slowRequests['p(95)']}ms`);
console.log(`p99: ${slowRequests['p(99)']}ms`);

// Check error patterns
const failedRequests = data.metrics.http_req_failed.values.rate;
if (failedRequests > 0.01) {
  console.error(`Error rate: ${failedRequests * 100}%`);
}
```

## Best Practices

### Test Types

1. **Smoke Test:** 1-2 VUs, 1-2 minutes
   - Verify system works under minimal load

2. **Load Test:** Expected normal/peak load, 5-15 minutes
   - Validate performance under typical conditions

3. **Stress Test:** Beyond peak load, gradually increase
   - Find breaking point

4. **Spike Test:** Sudden large increase, then drop
   - Test auto-scaling, recovery

5. **Soak Test:** Moderate load, 1+ hours
   - Find memory leaks, degradation

### Checklist

- [ ] Define performance requirements (SLAs)
- [ ] Identify critical user flows
- [ ] Prepare test data (users, content)
- [ ] Set up realistic scenarios
- [ ] Configure appropriate thresholds
- [ ] Test in staging environment first
- [ ] Monitor system resources during tests
- [ ] Analyze results against baselines
- [ ] Document bottlenecks and fixes
- [ ] Run tests regularly (CI/CD)
- [ ] Compare results over time

**Design load tests, execute tests, analyze results, provide optimization recommendations.**

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.