HTTP and REST load testing
HTTP and REST are the most common protocols you will load-test. Every MaxoPerf engine supports HTTP — Taurus native, JMeter, and k6 each offer a different trade-off between expressiveness, control, and ease of scripting. This page shows the common patterns and how to read HTTP results in MaxoPerf.
Before you start
Section titled “Before you start”- Read By engine — choosing your test engine to pick the right HTTP load tool.
- Read Taurus fundamentals if you plan to use Taurus native HTTP.
Taurus native HTTP
Section titled “Taurus native HTTP”Taurus’s built-in HTTP executor handles REST APIs without needing JMeter or k6. It is the fastest way to write a new HTTP load test for MaxoPerf.
execution: - concurrency: 100 ramp-up: 30s hold-for: 5m scenario: api-crud
scenarios: api-crud: default-address: https://api.example.com headers: Authorization: "Bearer ${TOKEN}" # injected from MaxoPerf secrets at run time Accept: application/json requests: - label: list-products url: /v1/products method: GET assert: - equals: subject: http-code value: '200'
- label: create-order url: /v1/orders method: POST headers: Content-Type: application/json body: '{"productId": "widget-01", "qty": 2}' assert: - contains: subject: body value: '"orderId"'
- label: get-order url: /v1/orders/${orderId} # extracted from previous response method: GET assert: - equals: subject: http-code value: '200'Extracting values between requests
Section titled “Extracting values between requests”Taurus supports extracting a value from one response and using it in the next request:
requests: - label: create-order url: /v1/orders method: POST body: '{"productId": "widget-01"}' extract-jsonpath: orderId: $.orderId # extract from response JSON
- label: get-order url: /v1/orders/${orderId} # use extracted value method: GETk6 HTTP patterns
Section titled “k6 HTTP patterns”k6’s http module gives full control over HTTP requests, with response checking and timing:
import http from 'k6/http';import { check } from 'k6';
export const options = { stages: [ { duration: '30s', target: 50 }, { duration: '3m', target: 50 }, { duration: '30s', target: 0 }, ],};
export default function () { // POST with JSON body const payload = JSON.stringify({ productId: 'widget-01', qty: 2 }); const params = { headers: { 'Content-Type': 'application/json' } };
const createRes = http.post('https://api.example.com/v1/orders', payload, params); check(createRes, { 'order created': (r) => r.status === 201 });
const orderId = createRes.json('orderId');
// GET with extracted value const getRes = http.get(`https://api.example.com/v1/orders/${orderId}`); check(getRes, { 'order found': (r) => r.status === 200 });}Authentication patterns
Section titled “Authentication patterns”Bearer token (from MaxoPerf secret)
Section titled “Bearer token (from MaxoPerf secret)”Configure the Authorization header with a MaxoPerf secret instead of hard-coding the token:
# Taurus YAMLscenarios: authed-api: headers: Authorization: "Bearer ${API_TOKEN}" # set API_TOKEN in Manage test secrets
requests: - url: /v1/protected-resource method: GETSee Manage test secrets for how to inject runtime secrets.
Login flow + token extraction
Section titled “Login flow + token extraction”For APIs that require a login step to obtain a token:
scenarios: login-and-call: requests: - label: login url: /v1/auth/login method: POST body: '{"email": "${USER_EMAIL}", "password": "${USER_PASSWORD}"}' headers: Content-Type: application/json extract-jsonpath: access_token: $.token
- label: get-profile url: /v1/me method: GET headers: Authorization: "Bearer ${access_token}"Reading HTTP results in MaxoPerf
Section titled “Reading HTTP results in MaxoPerf”After a run, the Overview tab shows the full HTTP result breakdown:
Key metrics to check:
| Panel | What to look for |
|---|---|
| Throughput chart | Flat line during hold-for = stable load. Dips indicate system or runner throttling. |
| Latency chart | p95 rising sharply under load = bottleneck. p50 and p95 diverging = high tail latency. |
| Error rate panel | Any non-2xx responses. Drill into the Log tab for the breakdown by endpoint and status code. |
| Per-endpoint panel | Compare latency across endpoints to find the slow one. |
Do / don’t
Section titled “Do / don’t”Do:
- Label every request in your scenario (
label:in Taurus,nametag in k6’shttp.get) — labels appear in the per-endpoint breakdown in MaxoPerf results. - Use extraction and parameterization for flows that span multiple requests.
- Set realistic think time (
sleep()in k6, orthink-time:in Taurus) between requests — pure closed-loop tests drive more RPS than real users would.
Don’t:
- Hard-code secrets (API tokens, passwords) in test files — inject them via MaxoPerf secrets.
- Test against production systems without authorization from your operations team and a clear communication plan.
- Ignore 4xx errors in results — a high rate of 400/401/404 responses usually indicates a test scripting problem, not a real load problem.
Where to go next
Section titled “Where to go next”- Cookbook: REST API CRUD load test — a full step-by-step recipe.
- Cookbook: auth login + token flow — login flow with token extraction.
- Cookbook: CSV data-driven test — parameterize requests with a CSV user list.
- GraphQL load testing — next protocol page.
- Failure criteria — set p95 thresholds that fail the run automatically.