Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.
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 minutehitspec 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
max
max<2s
Slowest response time
errors
errors<0.1%
Error rate: transport errors and non-2xx responses. Assertion failures are not counted here. errors<0 (or 0%) means no request may fail
assertions
assertions<1%
Share of checked responses that failed an assertion. assertions<0% means no assertion may fail
rps
rps>50
Minimum throughput in completed requests per second (uses > or >=)
Thresholds in profiles
In a hitspec.yaml stress profile, a threshold value may start with an operator: p95: "<=250ms", rps: ">=100", errors: "<=0". Without one, latency, error and assertion thresholds mean “less than” and rps means “greater than”. Quote values that start with an operator.
Requests that have expect assertions are checked in stress mode too. The results are kept apart so each threshold means one thing:
Errors (errors<...) are requests that failed in transport (connection refused, a client timeout, …) or came back with a non-2xx status. A non-2xx status that the request’s own expect status accepts (expect status 404 and the response is a 404) is expected, so it is not an error.
Assertion failures (assertions<...) are responses where at least one expect did not hold. A 200 whose body assertion fails is a success for errors and a failure for assertions. The summary prints Assertions: N checked, M failed, and --stress-json reports checked, failed and failureRate. snapshot assertions are skipped under load.
Incomplete requests were still in flight when the duration ended. They are reported on their own line and are not counted as requests, successes or errors, so a slow tail at the end of the window no longer inflates your error rate.
A run that falls more than 10% short of its target --rate prints a warning. When the server (or --max-vus) cannot keep up, the test sends less load than you asked for and the latencies understate what clients arriving on schedule would see, so do not read them as “the server handled N req/s”.
You can also assert on percentile latencies in your expect blocks:
>>>expect p95 < 200expect 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 500GET {{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.setupPOST {{baseUrl}}/api/initContent-Type: application/json{"seed": true}>>>expect status 200<<<>>>capturetestToken from body.token<<<### Main request (repeated during stress test)# @name mainRequest# @stress.weight 10GET {{baseUrl}}/api/dataAuthorization: Bearer {{setup.testToken}}>>>expect status 200<<<### Clean up (runs once after stress test)# @name teardown# @stress.teardownPOST {{baseUrl}}/api/cleanup>>>expect status 200<<<
Stress Profiles
Define reusable stress configurations in hitspec.yaml:
hitspec run api.http --stress --profile load --env staging
A flag you pass on the command line overrides the profile, even when it equals the flag’s default (--rate 10 wins over a profile’s rate: 100). Settings you do not pass come from the profile.
Using Profiles from studio
The hitspec studio stress screen runs a saved profile by name. Type it in the profile field and start the test: the profile’s duration, rate, VUs and thresholds apply, and any other field you fill in overrides it. The idle screen lists the profiles saved in hitspec.yaml. The desktop app can also create, edit, and delete profiles; changes are persisted to hitspec.yaml automatically.
Results Panel
After a stress test completes (either naturally or via stop), studio displays a results view 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 directoryhitspec run tests/ --stress --duration 1m --rate 100# Multiple specific fileshitspec 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:
# Prometheus endpoint (updated every second while the test runs)hitspec run api.http --stress --metrics prometheus --metrics-port 9090# JSON filehitspec run api.http --stress --metrics json --metrics-file metrics.json# DataDoghitspec run api.http --stress --metrics datadog --datadog-api-key $DD_API_KEY
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"hitspec","description":"hitspec is a file-based HTTP API testing tool. Write API tests as plain-text .http files, run them with 26 assertion operators, capture and chain requests, stress-test, mock, and verify database state — no SDK, no GUI, no JavaScript.","colors":{"primary":"#88C0D0","light":"#8FBCBB","dark":"#5E81AC"},"logo":{"light":"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/logo/light.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=b041ab9cc5b38b53110611b1c3e3435d","dark":"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/logo/dark.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=d9a717f6f6d804685a15907aa0d1f27e"},"favicon":"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/favicon.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=1f9aa7e4e0e34f5f9afb23c4165d8673","navbar":{"links":[{"href":"https://github.com/abdul-hamid-achik/hitspec","label":"GitHub"},{"href":"https://github.com/abdul-hamid-achik/hitspec/blob/main/CHANGELOG.md","label":"Changelog"}],"primary":{"type":"button","label":"Install","href":"/installation"}},"footer":{"socials":{"github":"https://github.com/abdul-hamid-achik/hitspec"}},"search":{"prompt":"Search the docs, syntax, and CLI…"},"seo":{"metatags":{"og:site_name":"hitspec","og:type":"website","og:locale":"en_US","twitter:card":"summary_large_image","theme-color":"#88C0D0","canonical":"https://hitspec.dev","robots":"index, follow","revisit-after":"7 days","language":"en"},"indexing":"navigable"},"metadata":{"timestamp":true},"styling":{"latex":false},"navigation":{"global":{"tabs":[{"tab":"Documentation","href":"/introduction"},{"tab":"Guides","href":"/guides"},{"tab":"Reference","href":"/reference"},{"tab":"Examples","href":"/examples"}],"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/abdul-hamid-achik/hitspec"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"fuego-45a05047","hasAudioNarration":false,"actualSubdomain":"fuego-45a05047","customDomains":["hitspec.dev"],"gitSource":{"type":"github","owner":"abdul-hamid-achik","repo":"hitspec","deployBranch":"main","contentDirectory":"apps/docs","isPrivate":true,"mountPath":"","label":""},"entitlements":{},"buildId":"6ad6611a7c2363fd57cca63a","clientVersion":"0.0.4143","searchFilterCounts":[{"language":"default","tag":"Features","count":17},{"language":"default","tag":"CLI Reference","count":13},{"language":"default","tag":"Guides","count":9},{"language":"default","tag":"Examples","count":8},{"language":"default","tag":"Core Concepts","count":7},{"language":"default","tag":"Getting Started","count":6},{"language":"default","tag":"Integrations","count":6},{"language":"default","tag":"Assertions Reference","count":2},{"language":"default","tag":"Configuration","count":2},{"language":"default","tag":"Authentication","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"landing.css","content":".hs-hero{position:relative;overflow:hidden;padding:6rem 1.5rem 4rem;background:radial-gradient(1200px 600px at 50% -10%, rgba(136, 192, 208, 0.18), transparent 60%),\n radial-gradient(800px 500px at 85% 10%, rgba(94, 129, 172, 0.16), transparent 55%),\n radial-gradient(700px 500px at 10% 20%, rgba(143, 188, 187, 0.14), transparent 55%)}@media (prefers-color-scheme: dark){.hs-hero{background:radial-gradient(1200px 600px at 50% -10%, rgba(136, 192, 208, 0.16), transparent 60%),\n radial-gradient(800px 500px at 85% 10%, rgba(94, 129, 172, 0.22), transparent 55%),\n radial-gradient(700px 500px at 10% 20%, rgba(143, 188, 187, 0.10), transparent 55%)}}.hs-hero::before{content:\"\";position:absolute;inset:0;background-image:linear-gradient(to right, rgba(136, 192, 208, 0.06) 1px, transparent 1px),\n linear-gradient(to bottom, rgba(136, 192, 208, 0.06) 1px, transparent 1px);background-size:48px 48px;mask-image:radial-gradient(ellipse 80% 60% at 50% 30%, black 40%, transparent 80%);-webkit-mask-image:radial-gradient(ellipse 80% 60% at 50% 30%, black 40%, transparent 80%);pointer-events:none}.hs-hero-inner{position:relative;max-width:72rem;margin:0 auto}.hs-badge{display:inline-flex;align-items:center;gap:0.5rem;padding:0.3rem 0.9rem;border-radius:999px;font-size:0.8rem;font-weight:500;letter-spacing:0.01em;color:#2e3440;background:rgba(136, 192, 208, 0.16);border:1px solid rgba(136, 192, 208, 0.35);backdrop-filter:blur(6px)}@media (prefers-color-scheme: dark){.hs-badge{color:#e5e9f0;background:rgba(136, 192, 208, 0.10);border:1px solid rgba(136, 192, 208, 0.25)}}.hs-badge-dot{width:0.5rem;height:0.5rem;border-radius:999px;background:#88c0d0;box-shadow:0 0 0 0 rgba(136, 192, 208, 0.7);animation:hs-pulse 2s infinite}@keyframes hs-pulse{0%{box-shadow:0 0 0 0 rgba(136, 192, 208, 0.6)}70%{box-shadow:0 0 0 8px rgba(136, 192, 208, 0)}100%{box-shadow:0 0 0 0 rgba(136, 192, 208, 0)}}.hs-headline{font-size:clamp(2.5rem, 6vw, 4.75rem);line-height:1.05;font-weight:700;letter-spacing:-0.02em;margin:1.25rem 0 0}.hs-gradient-text{background:linear-gradient(110deg, #5e81ac 0%, #88c0d0 45%, #8fbcbb 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}.hs-subhead{font-size:clamp(1.05rem, 2.2vw, 1.35rem);line-height:1.6;max-width:42rem;margin:1.5rem 0 0;color:#4c566a}@media (prefers-color-scheme: dark){.hs-subhead{color:#aeb6c6}}.hs-cta-row{display:flex;flex-wrap:wrap;gap:0.75rem;margin-top:2rem;align-items:center}.hs-btn{display:inline-flex;align-items:center;gap:0.5rem;padding:0.7rem 1.4rem;border-radius:0.75rem;font-weight:600;font-size:0.95rem;text-decoration:none;transition:transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease}.hs-btn-primary{color:#1b1f2a;background:linear-gradient(135deg, #88c0d0 0%, #8fbcbb 100%);box-shadow:0 10px 30px -10px rgba(136, 192, 208, 0.65)}.hs-btn-primary:hover{transform:translateY(-2px);box-shadow:0 16px 38px -12px rgba(136, 192, 208, 0.8)}@media (prefers-color-scheme: dark){.hs-btn-primary{color:#0d1117;background:linear-gradient(135deg, #88c0d0 0%, #a3d3df 100%)}}.hs-btn-ghost{color:#2e3440;background:rgba(46, 52, 64, 0.04);border:1px solid rgba(46, 52, 64, 0.18)}.hs-btn-ghost:hover{transform:translateY(-2px);background:rgba(46, 52, 64, 0.08)}@media (prefers-color-scheme: dark){.hs-btn-ghost{color:#e5e9f0;background:rgba(229, 233, 240, 0.04);border:1px solid rgba(229, 233, 240, 0.18)}.hs-btn-ghost:hover{background:rgba(229, 233, 240, 0.08)}}.hs-install-chip{display:inline-flex;align-items:center;gap:0.6rem;margin-top:1.5rem;padding:0.6rem 1rem;border-radius:0.6rem;font-family:ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, monospace;font-size:0.9rem;color:#2e3440;background:rgba(46, 52, 64, 0.05);border:1px solid rgba(46, 52, 64, 0.12)}@media (prefers-color-scheme: dark){.hs-install-chip{color:#d8dee9;background:rgba(216, 222, 233, 0.05);border:1px solid rgba(216, 222, 233, 0.12)}}.hs-install-chip code{background:transparent;border:none;padding:0;font-size:inherit}.hs-window{margin-top:2.5rem;border-radius:0.9rem;overflow:hidden;border:1px solid rgba(46, 52, 64, 0.14);background:#f6f8fa;box-shadow:0 24px 60px -28px rgba(46, 52, 64, 0.45)}@media (prefers-color-scheme: dark){.hs-window{border-color:rgba(216, 222, 233, 0.12);background:#161a23;box-shadow:0 24px 60px -28px rgba(0, 0, 0, 0.7)}}.hs-window-bar{display:flex;align-items:center;gap:0.45rem;padding:0.65rem 0.9rem;border-bottom:1px solid rgba(46, 52, 64, 0.10);background:rgba(46, 52, 64, 0.03)}@media (prefers-color-scheme: dark){.hs-window-bar{border-bottom-color:rgba(216, 222, 233, 0.10);background:rgba(216, 222, 233, 0.03)}}.hs-dot{width:0.75rem;height:0.75rem;border-radius:999px}.hs-dot-r{background:#ff5f57}.hs-dot-y{background:#febc2e}.hs-dot-g{background:#28c840}.hs-window-title{margin-left:0.5rem;font-size:0.78rem;color:#6b7280;font-family:ui-monospace, SFMono-Regular, Menlo, monospace}@media (prefers-color-scheme: dark){.hs-window-title{color:#8b93a7}}.hs-window pre{margin:0;padding:1.1rem 1.25rem;overflow-x:auto;font-family:ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, monospace;font-size:0.86rem;line-height:1.7;background:transparent!important}.hs-stats{display:grid;grid-template-columns:repeat(2, 1fr);gap:1rem;max-width:72rem;margin:0 auto;padding:0 1.5rem 3rem}@media (min-width: 768px){.hs-stats{grid-template-columns:repeat(4, 1fr)}}.hs-stat{text-align:center;padding:1.25rem 0.5rem;border-radius:0.85rem;border:1px solid rgba(46, 52, 64, 0.10);background:rgba(136, 192, 208, 0.05)}@media (prefers-color-scheme: dark){.hs-stat{border-color:rgba(216, 222, 233, 0.10);background:rgba(136, 192, 208, 0.05)}}.hs-stat-num{font-size:1.9rem;font-weight:700;line-height:1}.hs-stat-label{margin-top:0.4rem;font-size:0.82rem;color:#6b7280}@media (prefers-color-scheme: dark){.hs-stat-label{color:#8b93a7}}.hs-section{max-width:72rem;margin:0 auto;padding:3rem 1.5rem}.hs-eyebrow{text-transform:uppercase;letter-spacing:0.12em;font-size:0.78rem;font-weight:600;color:#5e81ac}.hs-h2{font-size:clamp(1.75rem, 3.5vw, 2.5rem);font-weight:700;letter-spacing:-0.015em;margin:0.5rem 0 0.5rem}.hs-lead{max-width:40rem;color:#4c566a;font-size:1.05rem;line-height:1.6}@media (prefers-color-scheme: dark){.hs-lead{color:#aeb6c6}}.hs-grid{display:grid;gap:1rem;grid-template-columns:1fr}@media (min-width: 640px){.hs-grid{grid-template-columns:repeat(2, 1fr)}}@media (min-width: 1024px){.hs-grid{grid-template-columns:repeat(3, 1fr)}}.hs-feature{display:block;padding:1.4rem;border-radius:0.9rem;border:1px solid rgba(46, 52, 64, 0.10);background:rgba(255, 255, 255, 0.6);text-decoration:none;transition:transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;backdrop-filter:blur(4px)}.hs-feature:hover{transform:translateY(-3px);border-color:rgba(136, 192, 208, 0.55);box-shadow:0 18px 40px -22px rgba(94, 129, 172, 0.45)}@media (prefers-color-scheme: dark){.hs-feature{border-color:rgba(216, 222, 233, 0.10);background:rgba(229, 233, 240, 0.03)}.hs-feature:hover{border-color:rgba(136, 192, 208, 0.55)}}.hs-feature-ico{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border-radius:0.7rem;font-size:1.1rem;background:linear-gradient(135deg, rgba(136, 192, 208, 0.25), rgba(94, 129, 172, 0.18));margin-bottom:0.85rem}.hs-feature-title{font-weight:600;font-size:1.02rem;color:#2e3440;margin:0}@media (prefers-color-scheme: dark){.hs-feature-title{color:#e5e9f0}}.hs-feature-desc{margin-top:0.4rem;font-size:0.9rem;line-height:1.55;color:#6b7280}@media (prefers-color-scheme: dark){.hs-feature-desc{color:#9ba3b3}}.hs-compare{width:100%;border-collapse:separate;border-spacing:0;font-size:0.92rem}.hs-compare th,.hs-compare td{padding:0.7rem 0.9rem;text-align:left;border-bottom:1px solid rgba(46, 52, 64, 0.08)}@media (prefers-color-scheme: dark){.hs-compare th,.hs-compare td{border-bottom-color:rgba(216, 222, 233, 0.08)}}.hs-compare th{font-weight:600;color:#2e3440;background:rgba(136, 192, 208, 0.06)}@media (prefers-color-scheme: dark){.hs-compare th{color:#e5e9f0}}.hs-compare tr:last-child td{border-bottom:none}.hs-yes{color:#28a745;font-weight:600}.hs-no{color:#9ba3b3}.hs-band{position:relative;overflow:hidden;padding:3.5rem 1.5rem;border-radius:1.25rem;max-width:72rem;margin:2rem auto;background:linear-gradient(135deg, rgba(94, 129, 172, 0.10), rgba(136, 192, 208, 0.08)),\n rgba(255, 255, 255, 0.5);border:1px solid rgba(136, 192, 208, 0.25)}@media (prefers-color-scheme: dark){.hs-band{background:linear-gradient(135deg, rgba(94, 129, 172, 0.16), rgba(136, 192, 208, 0.06)),\n rgba(229, 233, 240, 0.03);border-color:rgba(136, 192, 208, 0.20)}}.hs-final{position:relative;overflow:hidden;text-align:center;padding:5rem 1.5rem;max-width:72rem;margin:2rem auto 4rem;border-radius:1.5rem;background:radial-gradient(600px 300px at 50% 0%, rgba(136, 192, 208, 0.30), transparent 70%),\n linear-gradient(135deg, #5e81ac 0%, #88c0d0 100%);color:#fff}@media (prefers-color-scheme: dark){.hs-final{background:radial-gradient(600px 300px at 50% 0%, rgba(136, 192, 208, 0.35), transparent 70%),\n linear-gradient(135deg, #4c5e87 0%, #7fb3c4 100%);color:#0d1117}}.hs-final h2{font-size:clamp(1.8rem, 4vw, 2.75rem);font-weight:700;letter-spacing:-0.015em;margin:0}.hs-final p{margin:1rem auto 0;max-width:36rem;font-size:1.08rem;opacity:0.95}.hs-final .hs-btn-primary{background:#fff;color:#1b1f2a;box-shadow:0 12px 34px -12px rgba(0, 0, 0, 0.45)}.hs-final .hs-btn-primary:hover{background:#f6f8fa}.hs-faq{max-width:48rem;margin:0 auto;padding:1rem 1.5rem 3rem}body:has(.hs-hero) #page-title{display:none}"}],"page":{"pagePath":"features/stress-testing","slug":"/features/stress-testing","pageMetadata":{"title":"Load and stress test APIs with hitspec","description":"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.","keywords":["api stress testing","api load testing","hitspec stress","load testing cli","performance testing api"],"href":"/features/stress-testing"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Tip,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`hitspec includes built-in stress testing. Add `,_jsx(_components.code,{children:`--stress`}),` to your run command and your functional tests become load tests — no separate tool required.`]}),`\n`,_jsx(Heading,{level:`2`,id:`quick-start`,children:`Quick Start`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Send 100 requests per second for 1 minute`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --duration`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 1m`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --rate`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 100`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`two-modes`,children:`Two Modes`}),`\n`,_jsx(Heading,{level:`3`,id:`rate-mode`,children:`Rate Mode`}),`\n`,_jsx(_components.p,{children:`Controls throughput by setting a target number of requests per second:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --duration`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 1m`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --rate`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 50`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`virtual-users-vu-mode`,children:`Virtual Users (VU) Mode`}),`\n`,_jsx(_components.p,{children:`Simulates concurrent users, each making sequential requests with optional think time between them:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --duration`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 2m`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --vus`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 50`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --think-time`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 1s`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`ramp-up`,children:`Ramp-Up`}),`\n`,_jsx(_components.p,{children:`Gradually increase load instead of starting at full capacity:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --duration`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 5m`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --rate`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 200`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --ramp-up`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 30s`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`This linearly increases the request rate from 0 to 200 over the first 30 seconds, then holds at 200 for the remaining duration.`}),`\n`,_jsx(Heading,{level:`2`,id:`thresholds`,children:`Thresholds`}),`\n`,_jsx(_components.p,{children:`Set pass/fail criteria for CI/CD pipelines. If any threshold is exceeded, the command exits with a non-zero code:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -d`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 1m`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -r`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 100`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --threshold`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"p95\u003c200ms,errors\u003c0.1%\"`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Available threshold metrics:`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Metric`}),_jsx(_components.th,{children:`Example`}),_jsx(_components.th,{children:`Description`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`p50`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`p50\u003c100ms`})}),_jsx(_components.td,{children:`Median response time`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`p95`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`p95\u003c200ms`})}),_jsx(_components.td,{children:`95th percentile response time`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`p99`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`p99\u003c500ms`})}),_jsx(_components.td,{children:`99th percentile response time`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`max`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`max\u003c2s`})}),_jsx(_components.td,{children:`Slowest response time`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`errors`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`errors\u003c0.1%`})}),_jsxs(_components.td,{children:[`Error rate: transport errors and non-2xx responses. Assertion failures are not counted here. `,_jsx(_components.code,{children:`errors\u003c0`}),` (or `,_jsx(_components.code,{children:`0%`}),`) means no request may fail`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`assertions`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`assertions\u003c1%`})}),_jsxs(_components.td,{children:[`Share of checked responses that failed an assertion. `,_jsx(_components.code,{children:`assertions\u003c0%`}),` means no assertion may fail`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`rps`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`rps>50`})}),_jsxs(_components.td,{children:[`Minimum throughput in completed requests per second (uses `,_jsx(_components.code,{children:`>`}),` or `,_jsx(_components.code,{children:`>=`}),`)`]})]})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`thresholds-in-profiles`,children:`Thresholds in profiles`}),`\n`,_jsxs(_components.p,{children:[`In a `,_jsx(_components.code,{children:`hitspec.yaml`}),` stress profile, a threshold value may start with an operator: `,_jsx(_components.code,{children:`p95: \"\u003c=250ms\"`}),`, `,_jsx(_components.code,{children:`rps: \">=100\"`}),`, `,_jsx(_components.code,{children:`errors: \"\u003c=0\"`}),`. Without one, latency, error and assertion thresholds mean “less than” and `,_jsx(_components.code,{children:`rps`}),` means “greater than”. Quote values that start with an operator.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`9`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`stress`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` profiles`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` gate`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` duration`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`1m`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` rate`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`100`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` thresholds`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` p95`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"\u003c=250ms\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` rps`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\">=95\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` errors`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"0%\"`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`assertions-errors-and-incomplete-requests`,children:`Assertions, Errors and Incomplete Requests`}),`\n`,_jsxs(_components.p,{children:[`Requests that have `,_jsx(_components.code,{children:`expect`}),` assertions are checked in stress mode too. The results are kept apart so each threshold means one thing:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Errors`}),` (`,_jsx(_components.code,{children:`errors\u003c...`}),`) are requests that failed in transport (connection refused, a client timeout, …) or came back with a non-2xx status. A non-2xx status that the request’s own `,_jsx(_components.code,{children:`expect status`}),` accepts (`,_jsx(_components.code,{children:`expect status 404`}),` and the response is a 404) is expected, so it is not an error.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Assertion failures`}),` (`,_jsx(_components.code,{children:`assertions\u003c...`}),`) are responses where at least one `,_jsx(_components.code,{children:`expect`}),` did not hold. A `,_jsx(_components.code,{children:`200`}),` whose body assertion fails is a success for `,_jsx(_components.code,{children:`errors`}),` and a failure for `,_jsx(_components.code,{children:`assertions`}),`. The summary prints `,_jsx(_components.code,{children:`Assertions: N checked, M failed`}),`, and `,_jsx(_components.code,{children:`--stress-json`}),` reports `,_jsx(_components.code,{children:`checked`}),`, `,_jsx(_components.code,{children:`failed`}),` and `,_jsx(_components.code,{children:`failureRate`}),`. `,_jsx(_components.code,{children:`snapshot`}),` assertions are skipped under load.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Incomplete`}),` requests were still in flight when the duration ended. They are reported on their own line and are not counted as requests, successes or errors, so a slow tail at the end of the window no longer inflates your error rate.`]}),`\n`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`A run that falls more than 10% short of its target `,_jsx(_components.code,{children:`--rate`}),` prints a warning. When the server (or `,_jsx(_components.code,{children:`--max-vus`}),`) cannot keep up, the test sends less load than you asked for and the latencies understate what clients arriving on schedule would see, so do not read them as “the server handled N req/s”.`]})}),`\n`,_jsx(_components.p,{children:`You can also assert on percentile latencies in your expect blocks:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect p95 \u003c 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect p99 \u003c 500`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`stress-testing-flags`,children:`Stress Testing Flags`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Flag`}),_jsx(_components.th,{children:`Short`}),_jsx(_components.th,{children:`Description`}),_jsx(_components.th,{children:`Default`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--stress`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Enable stress testing mode`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`false`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--duration`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`-d`})}),_jsxs(_components.td,{children:[`Test duration (e.g., `,_jsx(_components.code,{children:`30s`}),`, `,_jsx(_components.code,{children:`2m`}),`, `,_jsx(_components.code,{children:`1h`}),`)`]}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`30s`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--rate`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`-r`})}),_jsx(_components.td,{children:`Target requests per second`}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`10`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--vus`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Number of virtual users`}),_jsx(_components.td,{})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--max-vus`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Maximum concurrent requests`}),_jsx(_components.td,{\"data-numeric\":`true`,children:_jsx(_components.code,{children:`100`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--think-time`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Delay between requests per VU`}),_jsx(_components.td,{})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--ramp-up`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Time to reach target rate/VUs`}),_jsx(_components.td,{})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--threshold`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Pass/fail thresholds`}),_jsx(_components.td,{})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--profile`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Load stress profile from config file`}),_jsx(_components.td,{})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--no-progress`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Disable real-time progress display`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`false`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`--stress-json`})}),_jsx(_components.td,{}),_jsx(_components.td,{children:`Output stress results as JSON`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`false`})})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`per-request-annotations`,children:`Per-Request Annotations`}),`\n`,_jsx(_components.p,{children:`Control how individual requests behave during stress tests:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`10`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`10`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Main API endpoint`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` apiCall`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @stress.weight 10`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @stress.think 500`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`GET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/data`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`available-annotations`,children:`Available Annotations`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Annotation`}),_jsx(_components.th,{children:`Description`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`@stress.weight \u003cn>`})}),_jsx(_components.td,{children:`Relative weight for request selection. Higher weight means more frequent execution.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`@stress.think \u003cms>`})}),_jsxs(_components.td,{children:[`Per-request think time in milliseconds (e.g., `,_jsx(_components.code,{children:`500`}),`, `,_jsx(_components.code,{children:`2000`}),`).`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`@stress.skip`})}),_jsx(_components.td,{children:`Exclude this request from stress testing.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`@stress.setup`})}),_jsx(_components.td,{children:`Run this request once before the stress test starts.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`@stress.teardown`})}),_jsx(_components.td,{children:`Run this request once after the stress test ends.`})]})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`setup-and-teardown`,children:`Setup and Teardown`}),`\n`,_jsxs(_components.p,{children:[`Use `,_jsx(_components.code,{children:`@stress.setup`}),` and `,_jsx(_components.code,{children:`@stress.teardown`}),` for one-time operations:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`37`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`37`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Initialize test data (runs once before stress test)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` setup`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @stress.setup`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`POST`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/init`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`Content-Type`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` application/json`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"seed\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`200`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>capture`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`testToken from body.token`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Main request (repeated during stress test)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` mainRequest`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @stress.weight 10`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`GET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/data`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`Authorization`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` Bearer {{setup.testToken}}`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Clean up (runs once after stress test)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` teardown`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @stress.teardown`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`POST`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/cleanup`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`stress-profiles`,children:`Stress Profiles`}),`\n`,_jsxs(_components.p,{children:[`Define reusable stress configurations in `,_jsx(_components.code,{children:`hitspec.yaml`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`22`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`22`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`stress`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` profiles`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` smoke`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` duration`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`30s`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` rate`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`10`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` maxVUs`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`5`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` load`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` duration`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`5m`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` rate`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`100`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` maxVUs`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`50`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` rampUp`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`30s`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` spike`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` duration`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`10m`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` vus`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`200`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` thinkTime`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`1s`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` thresholds`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` p95`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`500ms`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` errors`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`1%`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` conservative`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` duration`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`60s`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` rate`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1.5`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` maxVUs`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`2`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Run a profile:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --profile`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` load`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --env`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` staging`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`A flag you pass on the command line overrides the profile, even when it equals the flag’s default (`,_jsx(_components.code,{children:`--rate 10`}),` wins over a profile’s `,_jsx(_components.code,{children:`rate: 100`}),`). Settings you do not pass come from the profile.`]}),`\n`,_jsx(Heading,{level:`3`,id:`using-profiles-from-studio`,children:`Using Profiles from studio`}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.a,{href:`/guides/api-client-manager`,children:`hitspec studio`}),` stress screen runs a saved profile by name. Type it in the `,_jsx(_components.code,{children:`profile`}),` field and start the test: the profile’s duration, rate, VUs and thresholds apply, and any other field you fill in overrides it. The idle screen lists the profiles saved in `,_jsx(_components.code,{children:`hitspec.yaml`}),`. The desktop app can also create, edit, and delete profiles; changes are persisted to `,_jsx(_components.code,{children:`hitspec.yaml`}),` automatically.`]}),`\n`,_jsx(Heading,{level:`2`,id:`results-panel`,children:`Results Panel`}),`\n`,_jsx(_components.p,{children:`After a stress test completes (either naturally or via stop), studio displays a results view with:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Summary cards`}),` — Total requests, average RPS, success rate, and error count`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Latency percentiles`}),` — Min, P50, P95, P99, Max, Mean, and Standard Deviation (all in fractional milliseconds)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Per-request breakdown`}),` — A table showing each request’s count, success/error split, and individual latency metrics (avg, min, max, P50, P95, P99)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Threshold indicators`}),` — Pass/fail badges for each configured threshold`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Click `,_jsx(_components.strong,{children:`Run Again`}),` to return to the configuration view and start another test.`]}),`\n`,_jsxs(_components.p,{children:[`The results are also available programmatically via the `,_jsx(_components.a,{href:`/reference/rest-api#get-stress-test-result`,children:_jsx(_components.code,{children:`GET /api/v1/stress/result`})}),` endpoint.`]}),`\n`,_jsx(Heading,{level:`2`,id:`testing-directories-and-multiple-files`,children:`Testing Directories and Multiple Files`}),`\n`,_jsx(_components.p,{children:`Stress testing works with directories and multiple files:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# All files in a directory`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` tests/`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --duration`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 1m`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --rate`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 100`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Multiple specific files`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` users.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -d`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` 1m`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -r`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 100`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`understanding-rate-limits`,children:`Understanding Rate Limits`}),`\n`,_jsx(_components.p,{children:`Your server may have its own rate limits. High failure rates often indicate you are exceeding them.`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Server Limit`}),_jsx(_components.th,{children:`Equivalent`}),_jsxs(_components.th,{children:[`Safe `,_jsx(_components.code,{children:`--rate`}),` value`]})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`100 req/min`}),_jsx(_components.td,{children:`~1.67 req/s`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`--rate 1.5`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`600 req/min`}),_jsx(_components.td,{children:`10 req/s`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`--rate 8`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`1000 req/min`}),_jsx(_components.td,{children:`~16.7 req/s`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`--rate 15`})})]})]})]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`Start with a low rate and increase gradually. If you see high failure rates (above 10%), reduce `,_jsx(_components.code,{children:`--rate`}),` and `,_jsx(_components.code,{children:`--max-vus`}),`. Exactly N successes in 60 seconds often reveals a server-side rate limit of N req/min.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`ci/cd-integration`,children:`CI/CD Integration`}),`\n`,_jsx(_components.p,{children:`Use stress testing in GitHub Actions with thresholds:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`7`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`7`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`- `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`uses`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`abdul-hamid-achik/hitspec@v2`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` with`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` files`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`api.http`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` stress`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` duration`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`2m`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` rate`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`100`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` threshold`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`'p95\u003c200ms,errors\u003c0.5%'`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`metrics-export`,children:`Metrics Export`}),`\n`,_jsx(_components.p,{children:`Export stress test metrics to monitoring systems:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`8`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# Prometheus endpoint (updated every second while the test runs)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --metrics`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` prometheus`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --metrics-port`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 9090`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# JSON file`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --metrics`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` json`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --metrics-file`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` metrics.json`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# DataDog`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` api.http`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --stress`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --metrics`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` datadog`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --datadog-api-key`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` $DD_API_KEY`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`See the `,_jsx(_components.a,{href:`/integrations/github-actions`,children:`CI/CD integration guide`}),` for more details.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Load and stress test APIs with hitspec","description":"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.","keywords":["api stress testing","api load testing","hitspec stress","load testing cli","performance testing api"],"href":"/features/stress-testing"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Quick Start","slug":"quick-start","depth":2,"children":[]},{"title":"Two Modes","slug":"two-modes","depth":2,"children":[{"title":"Rate Mode","slug":"rate-mode","depth":3,"children":[]},{"title":"Virtual Users (VU) Mode","slug":"virtual-users-vu-mode","depth":3,"children":[]}]},{"title":"Ramp-Up","slug":"ramp-up","depth":2,"children":[]},{"title":"Thresholds","slug":"thresholds","depth":2,"children":[{"title":"Thresholds in profiles","slug":"thresholds-in-profiles","depth":3,"children":[]}]},{"title":"Assertions, Errors and Incomplete Requests","slug":"assertions-errors-and-incomplete-requests","depth":2,"children":[]},{"title":"Stress Testing Flags","slug":"stress-testing-flags","depth":2,"children":[]},{"title":"Per-Request Annotations","slug":"per-request-annotations","depth":2,"children":[{"title":"Available Annotations","slug":"available-annotations","depth":3,"children":[]},{"title":"Setup and Teardown","slug":"setup-and-teardown","depth":3,"children":[]}]},{"title":"Stress Profiles","slug":"stress-profiles","depth":2,"children":[{"title":"Using Profiles from studio","slug":"using-profiles-from-studio","depth":3,"children":[]}]},{"title":"Results Panel","slug":"results-panel","depth":2,"children":[]},{"title":"Testing Directories and Multiple Files","slug":"testing-directories-and-multiple-files","depth":2,"children":[]},{"title":"Understanding Rate Limits","slug":"understanding-rate-limits","depth":2,"children":[]},{"title":"CI/CD Integration","slug":"ci/cd-integration","depth":2,"children":[]},{"title":"Metrics Export","slug":"metrics-export","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"fuego-45a05047","siteName":"hitspec","title":"Load and stress test APIs with hitspec - hitspec","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-19T18:16:09.674Z","gitLastModified":"2026-10-19T18:16:02.000Z","originalFileLocation":"features/stress-testing.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.\">\u003cmeta data-mint-head name=\"application-name\" content=\"hitspec\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003cmeta data-mint-head name=\"robots\" content=\"index, follow\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Load and stress test APIs with hitspec - hitspec\">\u003cmeta data-mint-head property=\"og:description\" content=\"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"hitspec\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://hitspec.dev/features/stress-testing\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://fuego-45a05047.mintlify.site/_mintlify/api/og/v2?division=Features\u0026amp;title=Load+and+stress+test+APIs+with+hitspec\u0026amp;description=Load+test+APIs+with+hitspec+%E2%80%94+configurable+rate%2C+virtual+users%2C+ramp-up%2C+and+pass%2Ffail+thresholds.+No+separate+tool%3B+export+metrics+to+Prometheus+or+Datadog.\u0026amp;theme=93275042a6aa6480dea6ccca\u0026amp;signature=bfcbbd3c72440164c6d854a6afac42e1bb567be33b7970d01e6e5245627007f3\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Load and stress test APIs with hitspec - hitspec\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://fuego-45a05047.mintlify.site/_mintlify/api/og/v2?division=Features\u0026amp;title=Load+and+stress+test+APIs+with+hitspec\u0026amp;description=Load+test+APIs+with+hitspec+%E2%80%94+configurable+rate%2C+virtual+users%2C+ramp-up%2C+and+pass%2Ffail+thresholds.+No+separate+tool%3B+export+metrics+to+Prometheus+or+Datadog.\u0026amp;theme=93275042a6aa6480dea6ccca\u0026amp;signature=bfcbbd3c72440164c6d854a6afac42e1bb567be33b7970d01e6e5245627007f3\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"hitspec\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#88C0D0\">\u003cmeta data-mint-head name=\"og:locale\" content=\"en_US\">\u003cmeta data-mint-head name=\"theme-color\" content=\"#88C0D0\">\u003cmeta data-mint-head name=\"revisit-after\" content=\"7 days\">\u003cmeta data-mint-head name=\"language\" content=\"en\">\u003clink data-mint-head rel=\"canonical\" href=\"https://hitspec.dev/features/stress-testing\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/features/stress-testing.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://hitspec.dev/#organization\",\"name\":\"hitspec\",\"url\":\"https://hitspec.dev\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/logo/light.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=b041ab9cc5b38b53110611b1c3e3435d\"}},{\"@type\":\"WebSite\",\"@id\":\"https://hitspec.dev#website\",\"name\":\"hitspec\",\"url\":\"https://hitspec.dev\",\"publisher\":{\"@id\":\"https://hitspec.dev/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://hitspec.dev/features/stress-testing#webpage\",\"url\":\"https://hitspec.dev/features/stress-testing\",\"name\":\"Load and stress test APIs with hitspec\",\"description\":\"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.\",\"dateModified\":\"2026-10-19T18:16:02.000Z\",\"isPartOf\":{\"@id\":\"https://hitspec.dev#website\"},\"breadcrumb\":{\"@id\":\"https://hitspec.dev/features/stress-testing#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://hitspec.dev/features/stress-testing#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Features\",\"item\":\"https://hitspec.dev/features/authentication\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Load and stress test APIs with hitspec\",\"item\":\"https://hitspec.dev/features/stress-testing\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://hitspec.dev/features/stress-testing#article\",\"headline\":\"Load and stress test APIs with hitspec\",\"name\":\"Load and stress test APIs with hitspec\",\"description\":\"Load test APIs with hitspec — configurable rate, virtual users, ramp-up, and pass/fail thresholds. No separate tool; export metrics to Prometheus or Datadog.\",\"url\":\"https://hitspec.dev/features/stress-testing\",\"mainEntityOfPage\":{\"@id\":\"https://hitspec.dev/features/stress-testing#webpage\"},\"dateModified\":\"2026-10-19T18:16:02.000Z\",\"keywords\":\"api stress testing, api load testing, hitspec stress, load testing cli, performance testing api\",\"publisher\":{\"@id\":\"https://hitspec.dev/#organization\"},\"isPartOf\":{\"@id\":\"https://hitspec.dev#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"hitspec\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"hitspec\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/features/stress-testing.md","siteName":"hitspec","nav":{"global":{"tabs":[{"tab":"Documentation","href":"/introduction"},{"tab":"Guides","href":"/guides"},{"tab":"Reference","href":"/reference"},{"tab":"Examples","href":"/examples"}],"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/abdul-hamid-achik/hitspec"}]},"groups":[{"group":"Getting Started","pages":[{"title":"hitspec — Plain text API tests. No magic.","mode":"custom","href":"/introduction"},{"title":"Install hitspec — Homebrew, Go, and binary","href":"/installation"},{"title":"Write and run your first API test in under a minute","href":"/quickstart"},{"title":"hitspec studio — a keyboard-first terminal API client","href":"/studio"},{"title":"hitspec Studio desktop — a native GUI for .http files","href":"/desktop"},{"title":"Editor Setup","href":"/editor-setup"}]},{"group":"Core Concepts","pages":[{"title":"The .http file format for API tests","href":"/concepts/file-format"},{"title":"Variables","href":"/concepts/variables"},{"title":"Variable Interpolation","href":"/concepts/variable-interpolation"},{"title":"Assertions","href":"/concepts/assertions"},{"title":"Captures","href":"/concepts/captures"},{"title":"Dependencies","href":"/concepts/dependencies"},{"title":"Environments","href":"/concepts/environments"}]},{"group":"Features","pages":[{"title":"Authentication for API tests (@auth)","href":"/features/authentication"},{"title":"Multipart and GraphQL","href":"/features/multipart-graphql"},{"title":"TLS, cookies and HTTP options","href":"/features/tls-and-cookies"},{"title":"Snapshot testing for API responses","description":"Capture API response bodies as baselines and automatically detect regressions with snapshot comparison. Update baselines on purposeful changes.","href":"/features/snapshot-testing"},{"title":"Load and stress test APIs with hitspec","href":"/features/stress-testing"},{"title":"Database assertions after HTTP requests","description":"Verify database state after HTTP requests with SQL queries and assertions. Use >>>db blocks to check side effects in PostgreSQL, MySQL, and SQLite.","href":"/features/database-assertions"},{"title":"Shell Commands","href":"/features/shell-commands"},{"title":"Hooks","href":"/features/hooks"},{"title":"Server-Sent Events (SSE)","href":"/features/sse"},{"title":"API Coverage","href":"/features/api-coverage"},{"title":"Mock server from .http files","href":"/features/mock-server"},{"title":"Contract Testing","href":"/features/contract-testing"},{"title":"Recording Proxy","href":"/features/recording-proxy"},{"title":"Watch Mode","href":"/features/watch-mode"},{"title":"Parallel Execution","href":"/features/parallel-execution"},{"title":"Notifications","href":"/features/notifications"},{"title":"Metrics Export","href":"/features/metrics-export"}]},{"group":"Guides","pages":[{"title":"hitspec studio","icon":"terminal","href":"/guides/api-client-manager"},{"title":"CI/CD Pipeline Integration","href":"/guides/ci-cd-pipeline"},{"title":"Regression Testing with hitspec diff","href":"/guides/regression-testing"},{"title":"Database Testing Guide","href":"/guides/database-testing"},{"title":"Load Testing Guide","href":"/guides/load-testing"},{"title":"Contract Testing Guide","href":"/guides/contract-testing"},{"title":"Migrate from Postman to hitspec .http tests","href":"/guides/migrating-from-postman"},{"title":"Upgrading","icon":"arrow-up","href":"/guides/upgrading"},{"title":"Troubleshooting","icon":"wrench","href":"/guides/troubleshooting"}]},{"group":"Examples","pages":[{"title":"Basic CRUD","href":"/examples/basic-crud"},{"title":"Auth Flow","href":"/examples/auth-flow"},{"title":"GraphQL","href":"/examples/graphql"},{"title":"CI/CD Integration","href":"/examples/ci-cd"},{"title":"Stress Testing","href":"/examples/stress-testing"},{"title":"Database Assertions","href":"/examples/database-assertions"},{"title":"Contract Testing","href":"/examples/contract-testing"},{"title":"Mock Server","href":"/examples/mock-server"}]},{"group":"CLI Reference","pages":[{"title":"hitspec run","href":"/reference/run"},{"title":"hitspec validate \u0026 list","href":"/reference/validate-list"},{"title":"hitspec init","href":"/reference/init"},{"title":"hitspec import \u0026 export","href":"/reference/import-export"},{"title":"hitspec mock \u0026 record","href":"/reference/mock-record"},{"title":"hitspec contract \u0026 diff","href":"/reference/contract-diff"},{"title":"hitspec docs, studio \u0026 serve","href":"/reference/docs-serve"},{"title":"Fetch responses","href":"/reference/fetch"},{"title":"MCP client and server","href":"/reference/mcp"},{"title":"REST API","icon":"code","href":"/reference/rest-api"},{"title":"hitspec completion","href":"/reference/completion"},{"title":"hitspec version","href":"/reference/version"},{"title":"Exit Codes","href":"/reference/exit-codes"}]},{"group":"Configuration","pages":[{"title":"Configuration Reference","href":"/reference/configuration"},{"title":"Environment Variables","href":"/reference/environment-variables"}]},{"group":"Assertions Reference","pages":[{"title":"Assertion Operators","href":"/reference/assertion-operators"},{"title":"Assertion Subjects","href":"/reference/assertion-subjects"}]},{"group":"Built-in Functions","pages":[{"title":"Built-in Functions","href":"/reference/builtin-functions"}]},{"group":"Authentication","pages":[{"title":"Authentication Types","href":"/reference/auth-types"}]},{"group":"Output Formats","pages":[{"title":"Output Formats","href":"/reference/output-formats"}]},{"group":"Integrations","pages":[{"title":"GitHub Actions","href":"/integrations/github-actions"},{"title":"Output Formats","href":"/integrations/output-formats"},{"title":"Prometheus","href":"/integrations/prometheus"},{"title":"DataDog","href":"/integrations/datadog"},{"title":"Slack \u0026 Teams Notifications","href":"/integrations/slack-teams"},{"title":"Agent artifact workflow","href":"/integrations/agent-artifacts"}]}]},"basePath":"","title":"Load and stress test APIs with hitspec - hitspec","buildId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","deploymentId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","dynamics":[],"chunks":[]}