hitspec includes built-in stress testing. Add --stress to your run command and your functional tests become load tests — no separate tool required.
Quick Start
# Send 100 requests per second for 1 minute
hitspec run api.http --stress --duration 1m --rate 100
Two Modes
Rate Mode
Controls throughput by setting a target number of requests per second:
hitspec run api.http --stress --duration 1m --rate 50
Virtual Users (VU) Mode
Simulates concurrent users, each making sequential requests with optional think time between them:
hitspec run api.http --stress --duration 2m --vus 50 --think-time 1s
Ramp-Up
Gradually increase load instead of starting at full capacity:
hitspec run api.http --stress --duration 5m --rate 200 --ramp-up 30s
This linearly increases the request rate from 0 to 200 over the first 30 seconds, then holds at 200 for the remaining duration.
Thresholds
Set pass/fail criteria for CI/CD pipelines. If any threshold is exceeded, the command exits with a non-zero code:
hitspec run api.http --stress -d 1m -r 100 --threshold "p95<200ms,errors<0.1%"
Available threshold metrics:
| Metric | Example | Description |
|---|
p50 | p50<100ms | Median response time |
p95 | p95<200ms | 95th percentile response time |
p99 | p99<500ms | 99th percentile response time |
errors | errors<0.1% | Error rate percentage |
You can also assert on percentile latencies in your expect blocks:
>>>
expect p95 < 200
expect p99 < 500
<<<
Stress Testing Flags
| Flag | Short | Description | Default |
|---|
--stress | | Enable stress testing mode | false |
--duration | -d | Test duration (e.g., 30s, 2m, 1h) | 30s |
--rate | -r | Target requests per second | 10 |
--vus | | Number of virtual users | |
--max-vus | | Maximum concurrent requests | 100 |
--think-time | | Delay between requests per VU | |
--ramp-up | | Time to reach target rate/VUs | |
--threshold | | Pass/fail thresholds | |
--profile | | Load stress profile from config file | |
--no-progress | | Disable real-time progress display | false |
--stress-json | | Output stress results as JSON | false |
Per-Request Annotations
Control how individual requests behave during stress tests:
### Main API endpoint
# @name apiCall
# @stress.weight 10
# @stress.think 500
GET {{baseUrl}}/api/data
>>>
expect status 200
<<<
Available Annotations
| Annotation | Description |
|---|
@stress.weight <n> | Relative weight for request selection. Higher weight means more frequent execution. |
@stress.think <ms> | Per-request think time in milliseconds (e.g., 500, 2000). |
@stress.skip | Exclude this request from stress testing. |
@stress.setup | Run this request once before the stress test starts. |
@stress.teardown | Run this request once after the stress test ends. |
Setup and Teardown
Use @stress.setup and @stress.teardown for one-time operations:
### Initialize test data (runs once before stress test)
# @name setup
# @stress.setup
POST {{baseUrl}}/api/init
Content-Type: application/json
{"seed": true}
>>>
expect status 200
<<<
>>>capture
testToken from body.token
<<<
### Main request (repeated during stress test)
# @name mainRequest
# @stress.weight 10
GET {{baseUrl}}/api/data
Authorization: Bearer {{setup.testToken}}
>>>
expect status 200
<<<
### Clean up (runs once after stress test)
# @name teardown
# @stress.teardown
POST {{baseUrl}}/api/cleanup
>>>
expect status 200
<<<
Stress Profiles
Define reusable stress configurations in hitspec.yaml:
stress:
profiles:
smoke:
duration: 30s
rate: 10
maxVUs: 5
load:
duration: 5m
rate: 100
maxVUs: 50
rampUp: 30s
spike:
duration: 10m
vus: 200
thinkTime: 1s
thresholds:
p95: 500ms
errors: 1%
conservative:
duration: 60s
rate: 1.5
maxVUs: 2
Run a profile:
hitspec run api.http --stress --profile load --env staging
Managing Profiles from the Web UI
The API Client Manager stress test view lets you create, edit, and delete profiles without touching hitspec.yaml directly. Select a profile from the dropdown to populate the stress config fields, or click New Profile to save the current configuration. All changes are persisted to hitspec.yaml automatically.
Results Panel
After a stress test completes (either naturally or via stop), the web UI displays a results dashboard with:
- Summary cards — Total requests, average RPS, success rate, and error count
- Latency percentiles — Min, P50, P95, P99, Max, Mean, and Standard Deviation (all in fractional milliseconds)
- Per-request breakdown — A table showing each request’s count, success/error split, and individual latency metrics (avg, min, max, P50, P95, P99)
- Threshold indicators — Pass/fail badges for each configured threshold
Click Run Again to return to the configuration view and start another test.
The results are also available programmatically via the GET /api/v1/stress/result endpoint.
Testing Directories and Multiple Files
Stress testing works with directories and multiple files:
# All files in a directory
hitspec run tests/ --stress --duration 1m --rate 100
# Multiple specific files
hitspec run api.http users.http --stress -d 1m -r 100
Understanding Rate Limits
Your server may have its own rate limits. High failure rates often indicate you are exceeding them.
| Server Limit | Equivalent | Safe --rate value |
|---|
| 100 req/min | ~1.67 req/s | --rate 1.5 |
| 600 req/min | 10 req/s | --rate 8 |
| 1000 req/min | ~16.7 req/s | --rate 15 |
Start with a low rate and increase gradually. If you see high failure rates (above 10%), reduce --rate and --max-vus. Exactly N successes in 60 seconds often reveals a server-side rate limit of N req/min.
CI/CD Integration
Use stress testing in GitHub Actions with thresholds:
- uses: abdul-hamid-achik/hitspec@v1
with:
files: api.http
stress: true
duration: 2m
rate: 100
threshold: 'p95<200ms,errors<0.5%'
Metrics Export
Export stress test metrics to monitoring systems:
# Prometheus endpoint
hitspec run api.http --stress --metrics prometheus --metrics-port 9090
# JSON file
hitspec run api.http --stress --metrics json --metrics-file metrics.json
# DataDog
hitspec run api.http --stress --metrics datadog --datadog-api-key $DD_API_KEY
See the CI/CD integration guide for more details.