Skip to content

CI-gated performance test

Problem: Deployments can introduce performance regressions. You want your CI pipeline to run a performance test on every release candidate, report the key metrics, and fail the build if the result is worse than your baseline — before the code ships to production.

Test type: Baseline regression test triggered from CI.

  • A MaxoPerf account with a test that has a clean baseline run.
  • A MaxoPerf API token stored as a secret in your CI provider (GitHub Actions, GitLab CI, CircleCI, etc.).
  • Failure criteria configured on the test — the criteria determine whether the run ends with status finished (pass) or failed (fail).
  • The test ID from the MaxoPerf console (visible in the URL when the test is open: /tests/tst-xxxxxxxx).

See Run tests from CI for the how-to reference.

Before wiring up CI, make sure the test knows when to fail. In the MaxoPerf console:

  1. Open the test, switch to Configuration, and scroll to Failure criteria.
  2. Add your thresholds — for example p95 latency > 300ms and error rate > 0.5 %.
  3. Save.

The CI pipeline will use the run status field to decide pass/fail — no custom logic in CI needed.

In your CI provider, add a secret named MAXOPERF_TOKEN with the value of your Maxoperf API token.

GitHub Actions example:

.github/workflows/perf-gate.yml
name: Performance gate
on:
push:
branches: [main, 'release/**']
jobs:
perf:
runs-on: ubuntu-latest
steps:
- name: Trigger MaxoPerf run
id: start
run: |
RUN=$(curl -sf -X POST \
-H "Authorization: Bearer ${{ secrets.MAXOPERF_TOKEN }}" \
-H "Content-Type: application/json" \
https://api.maxoperf.com/v1/runs \
-d '{"test_id": "tst-1234abcd56"}')
echo "run_id=$(echo $RUN | jq -r .id)" >> $GITHUB_OUTPUT
- name: Wait for run to complete
run: |
for i in $(seq 1 60); do
STATUS=$(curl -sf \
-H "Authorization: Bearer ${{ secrets.MAXOPERF_TOKEN }}" \
https://api.maxoperf.com/v1/runs/${{ steps.start.outputs.run_id }} \
| jq -r .status)
echo "Run status: $STATUS"
if [ "$STATUS" = "finished" ]; then
echo "Run passed failure criteria."
exit 0
elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "cancelled" ]; then
echo "Run did not pass failure criteria — status: $STATUS"
exit 1
fi
sleep 10
done
echo "Timed out waiting for run."
exit 1

Replace tst-1234abcd56 with your real test ID.

GitLab CI example:

perf-gate:
stage: test
script:
- |
RUN_ID=$(curl -sf -X POST \
-H "Authorization: Bearer $MAXOPERF_TOKEN" \
-H "Content-Type: application/json" \
https://api.maxoperf.com/v1/runs \
-d "{\"test_id\": \"tst-1234abcd56\"}" | jq -r .id)
echo "Started run: $RUN_ID"
for i in $(seq 1 60); do
STATUS=$(curl -sf \
-H "Authorization: Bearer $MAXOPERF_TOKEN" \
https://api.maxoperf.com/v1/runs/$RUN_ID | jq -r .status)
[ "$STATUS" = "finished" ] && exit 0
[ "$STATUS" = "failed" ] && exit 1
sleep 10
done
exit 1
  1. Open the Runs list in the MaxoPerf console after the CI step fires.
  2. The run started by CI appears with the test name and a timestamp matching the pipeline execution.
  3. Click the run to see the full result — per-label latency, error rate, and the failure-criteria verdict.
  • The CI step exits 0 when the run status is finished and 1 when it is failed.
  • The run appears in the MaxoPerf console with a source tag identifying the CI trigger.
  • Failure criteria violations show on the run overview with the exact threshold that was breached.
  • Override load profile per branch: pass "overrides": {"concurrency": 5} in the trigger payload for feature-branch runs to use a lighter load than the main-branch gate.
  • Tag the run with commit SHA: add "tags": {"commit": "$GITHUB_SHA"} to the trigger body for searchable run history.
  • Webhook instead of polling: configure a MaxoPerf webhook to POST to your CI pipeline’s callback URL on run completion — eliminates the polling loop.
  • Parallel CI jobs: trigger a matrix of tests (smoke, load, API) in parallel CI jobs; each polls its own run_id.