Skip to main content
โšก Calmops

Performance Testing: Load Testing with k6 and Artillery

Introduction

Performance testing ensures your system can handle expected load. This guide covers load testing with k6 and Artillery - modern, scriptable tools for testing API and web performance.


Testing Types

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                Performance Testing Types                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                             โ”‚
โ”‚  Load Testing                                              โ”‚
โ”‚  โ€ข Normal expected load                                    โ”‚
โ”‚  โ€ข Peak load scenarios                                     โ”‚
โ”‚  โ€ข Duration: 10-30 minutes                                 โ”‚
โ”‚                                                             โ”‚
โ”‚  Stress Testing                                           โ”‚
โ”‚  โ€ข Beyond normal capacity                                  โ”‚
โ”‚  โ€ข Find breaking point                                     โ”‚
โ”‚  โ€ข Test recovery                                          โ”‚
โ”‚                                                             โ”‚
โ”‚  Spike Testing                                            โ”‚
โ”‚  โ€ข Sudden traffic increase                                โ”‚
โ”‚  โ€ข How fast can you scale?                                โ”‚
โ”‚                                                             โ”‚
โ”‚  Soak Testing                                             โ”‚
โ”‚  โ€ข Extended period (hours)                                โ”‚
โ”‚  โ€ข Find memory leaks                                      โ”‚
โ”‚                                                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

k6

Setup

# Install k6
brew install k6
# or
npm install -D k6

# Run test
k6 run test.js

Basic Script

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

export const options = {
  stages: [
    { duration: '30s', target: 10 },   // Ramp up
    { duration: '1m', target: 10 },  // Stay at 10 users
    { duration: '30s', target: 0 },  // Ramp down
  ],
};

export default function () {
  const res = http.get('https://api.example.com/users');
  
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });
  
  sleep(1);
}

Advanced Options

export const options = {
  // Virtual users
  vus: 10,
  duration: '2m',
  
  // Thresholds (fail test if exceeded)
  thresholds: {
    http_req_duration: ['p(95)<500'],  // 95% under 500ms
    http_req_failed: ['rate<0.01'],  // Error rate < 1%
  },
  
  // Setup and teardown
  setup: () => { /* run once */ },
  teardown: () => {/* run once */},
};

export default function () {
  // Group related requests
  group('User flow', () => {
    const login = http.post('/login', JSON.stringify({email: '[email protected]'}));
    
    check(login, { 'login success': (r) => r.status === 200 });
    
    const user = http.get('/profile', {
      headers: { 'Authorization': `Bearer ${login.json().token}` },
    });
    
    check(user, { 'get profile': (r) => r.status === 200 });
  });
}

Artillery

Setup

npm install -D artillery

YAML Configuration

# test-config.yml
config:
  target: "https://api.example.com"
  phases:
    - duration: 60
      arrivalRate: 5
      name: "Warm up"
    - duration: 120
      arrivalRate: 20
      name: "Sustained load"
    - duration: 30
      arrivalRate: 50
      name: "Stress test"
  
  plugins:
    expect: {}
  
  processor: "./handlers.js"

scenarios:
  - name: "Get users"
    flow:
      - get:
          url: "/api/users"
          capture:
            - json: "$.users[0].id"
              as: "userId"
          expect:
            - statusCode: 200
            - contentType: json
    
  - name: "Create user"
    flow:
      - post:
          url: "/api/users"
          json:
            name: "Test User"
            email: "[email protected]"
          expect:
            - statusCode: 201

Running

# Run test
npx artillery run test-config.yml

# Quick test
npx artillery quick --duration 10 --rate 10 https://api.example.com

Metrics to Track

# Key performance metrics
metrics:
  response_time:
    - "p50: Median response time"
    - "p95: 95th percentile"
    - "p99: 99th percentile"
    
  throughput:
    - "requests per second"
    - "transactions per second"
    
  errors:
    - "error rate"
    - "timeout rate"
    
  resources:
    - "CPU usage"
    - "Memory usage"
    - "Network I/O"

CI Integration

# GitHub Actions
- name: Load Test
  run: |
    k6 run \
      --out json=k6-results.json \
      --summary-export=k6-summary.json \
      test.js
  env:
    K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}

Key Takeaways

  • k6 - Scriptable, JavaScript, great for developers
  • Artillery - YAML-based, simple configuration
  • Test early - Catch performance issues in CI
  • Set thresholds - Fail builds on regressions

External Resources

Comments