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¶
- Creates a test order using
POST /api/v1/test-seeding/orders - Test order uses prefix
TEST-LOAD-for easy identification - Stores order ID for use during test execution
Execution Phase¶
- Uses the seeded order ID for all detail requests
- All HTTP requests return 2xx status codes
- No 404 errors from non-existent orders
Teardown Phase¶
- Cleans up test data using
DELETE /api/v1/test-seeding/cleanup - Removes all
TEST-prefixed orders, mappings, and logs - 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¶
- Navigate to Pipelines in Azure DevOps
- Click Run pipeline on the main branch
- Enable "Run Load Tests (optional)" checkbox
- 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)