Skip to content

Load Testing Guide

Version: 1.0
Date: January 18, 2026

Overview

Forma3D.Connect uses K6 for load testing to verify the system can handle expected production workloads (500+ orders/day). Load tests can be run locally, against staging, or as part of the CI/CD pipeline.

Quick Start

# Install K6 (if not already installed)
brew install k6

# Run against local environment
pnpm load-test:local

# Run against staging
pnpm load-test:staging

# Run dashboard load test
pnpm load-test:dashboard

Test Scenarios

Order Throughput (order-throughput.js)

Simulates the expected daily order volume with sustained load and optional spike testing.

Parameter Default Description
ENV local Target environment (local, staging)
DURATION 2m Test duration
SPIKE true Enable spike test after sustained load
BASELINE false Collect data without failing on thresholds

What it tests: - Health check endpoint responsiveness - Order list API performance - Order detail API performance - System stability under sustained load - Recovery from traffic spikes

Dashboard Load (dashboard-load.js)

Simulates concurrent dashboard users accessing the system.

What it tests: - Multiple simultaneous users - Dashboard page load times - Real-time WebSocket connections

Thresholds

Performance thresholds are aligned with Non-Functional Requirements (NFRs):

Metric Threshold NFR Reference
HTTP request duration p(95) < 2000ms NFR-PE-003
HTTP request failed < 1% NFR-AV-001
Checks pass rate > 99% -
Health check success > 99% -
Order list success > 99% -

Test Data Seeding

Load tests automatically seed test data to ensure consistent, reliable results:

Setup Phase

  1. Creates a test order using POST /api/v1/test-seeding/orders
  2. Test order uses prefix TEST-LOAD- for easy identification
  3. Stores order ID for use during test execution

Execution Phase

  1. Uses the seeded order ID for all detail requests
  2. All HTTP requests return 2xx status codes
  3. No 404 errors from non-existent orders

Teardown Phase

  1. Cleans up test data using DELETE /api/v1/test-seeding/cleanup
  2. Removes all TEST- prefixed orders, mappings, and logs
  3. Only cleans up if seeding was successful (doesn't delete real orders)

Fallback Behavior

If test seeding is unavailable (e.g., NODE_ENV=production): 1. Falls back to using existing orders from the database 2. If no orders exist, fails with a clear error message

Running in CI/CD Pipeline

Enabling Load Tests

  1. Navigate to Pipelines in Azure DevOps
  2. Click Run pipeline on the main branch
  3. Enable "Run Load Tests (optional)" checkbox
  4. Click Run

Pipeline Parameters

Parameter Type Default Description
runLoadTests boolean false Enable load test stage
loadTestBaselineMode boolean false Collect data without failing

Stage Dependencies

The Load Test stage: - Depends on: Build, AcceptanceTest - Runs after: AcceptanceTest (or skipped stages) - Publishes: HTML report, JSON metrics as artifacts

Viewing Results

After the pipeline completes: 1. Navigate to the pipeline run 2. Click on the HTML Viewer tab 3. Select K6 Load Test Report

The report displays: - Key Metrics — Visual cards showing p95/p99 response times, fail rate, total requests, and checks passed - Raw Summary Data — Complete JSON output from K6 - Configuration — Target URL, environment, duration - Thresholds — Pass/fail criteria

Artifacts are also available for download: - load-test-results/report.html - Visual HTML report - load-test-results/order-throughput-summary.json - JSON metrics - load-test-results/order-throughput.json - Full K6 output (for detailed analysis)

Baseline Mode

Use baseline mode to collect performance data without failing the pipeline:

# Command line
k6 run --env BASELINE=true load-tests/k6/scenarios/order-throughput.js

# Pipeline
# Check "Load Test Baseline Mode" when running the pipeline

When to use baseline mode: - Establishing initial performance baselines - Comparing performance before/after changes - Testing against unknown environments - Debugging threshold configurations

Local Development

Prerequisites

# Install K6
brew install k6

# Start local services
pnpm dev

Running Tests

# Quick test (1 minute, no spike)
k6 run --env ENV=local --env DURATION=1m --env SPIKE=false \
  load-tests/k6/scenarios/order-throughput.js

# Full test with JSON output
k6 run --env ENV=local \
  --out json=load-tests/results/local.json \
  load-tests/k6/scenarios/order-throughput.js

Viewing Results

# Summary is printed to console after test completion

# For detailed analysis, use the JSON output with K6 Cloud or Grafana

Troubleshooting

High Failure Rate (> 1%)

Symptoms: http_req_failed threshold crossed

Possible causes: - External service (Shopify, SimplyPrint, Sendcloud) is down - Database connection pool exhausted - Rate limiting triggered

Resolution: 1. Check /health/dependencies for service status 2. Review Sentry for error spikes 3. Increase DATABASE_POOL_SIZE if needed 4. Check rate limit configuration

Slow Response Times (p95 > 2s)

Symptoms: http_req_duration threshold crossed

Possible causes: - Database queries are slow - N+1 query patterns - Resource contention on server

Resolution: 1. Review database query performance in Sentry 2. Check for missing indexes 3. Monitor CPU/memory on the droplet

Test Seeding Failures

Symptoms: Test fails with "No test order available"

Possible causes: - Running against production (NODE_ENV=production) - Test seeding module not loaded - Database connection issues

Resolution: 1. Verify environment is staging, not production 2. Check API logs for test-seeding errors 3. Verify database connectivity

Pipeline Stage Skipped

Symptoms: Load Test stage shows as "Skipped"

Possible causes: - runLoadTests parameter not enabled - AcceptanceTest stage failed - Not running on main branch

Resolution: 1. Enable "Run Load Tests" when triggering pipeline 2. Check AcceptanceTest results 3. Ensure running on main branch

Configuration

Environment Variables

Variable Default Description
API_URL From config Target API base URL
API_KEY From config Internal API key for authenticated endpoints
ENV local Environment name
DURATION 2m Test duration
SPIKE true Enable spike test
BASELINE false Baseline mode (no threshold failures)

File Structure

load-tests/
├── k6/
│   ├── config.js           # Shared configuration
│   └── scenarios/
│       ├── order-throughput.js   # Main load test
│       └── dashboard-load.js     # Dashboard simulation
└── results/                # Test output (gitignored)