quizbase
Skip to content
Command Palette
Search for a command to run...
QuizBase · Docs

Performance#

QuizBase is built and load-tested as a developer-grade API. This page lists the measured numbers, the methodology behind them, and how we keep them honest.

All figures below come from k6 sustained load tests against production (quizbase.runriva.com) on 2026-05-30. We re-run baseline + spike scenarios quarterly and after significant changes — this run lands lower p95 across the board than the previous one. Latest raw output: k6-baseline-2026-05-30.json.

Service Level Objectives#

Measured over a full 5-minute sustained run at 50 RPS (15,002 requests, 0.01% errors). Figures are client-side, measured over the public internet — your latency depends on your distance to the EU region.

MetricTargetMeasured (2026-05-30)
p95, discovery endpoints (categories/stats/tags…)< 200ms~45ms
p95, questions browse + PK lookup< 500ms~90ms
p95, random (randomized sampling, heaviest)< 800ms~265ms
Error rate (sustained 50 RPS)< 1%0.01% (2 / 15,002)
Sustained throughput50 RPS48.7 RPS (15,002 requests)
Uptime99.9%Live status

x-performance extension on every operation in the OpenAPI spec reports the same numbers per-endpoint — machine-readable for your monitoring or SDK telemetry.

Per-endpoint performance#

Sustained 50 RPS for 5 minutes (60% public discovery / 30% browse / 10% random + PK lookup), 15,002 requests measured. Mix matches realistic API usage — most clients are discovery/browse, fewer random pulls, fewest PK lookups.

Endpointp50p90p95Sustained RPS
GET /api/v1/categories22ms29ms43ms50
GET /api/v1/stats23ms28ms41ms50
GET /api/v1/topics22ms28ms46ms50
GET /api/v1/tags22ms28ms45ms50
GET /api/v1/subcategories22ms28ms40ms50
GET /api/v1/questions57ms69ms91ms50
GET /api/v1/questions/random (broad)211ms245ms265ms50
GET /api/v1/questions/:id53ms65ms82ms50

Numbers are client-side over the public internet (TCP + TLS + network RTT included), so they are an upper bound on what the API itself spends. /v1/me, /v1/usage, /v1/languages, /v1/topics/:slug, /v1/report are not part of the load mix (small payloads, low-traffic endpoints) but stay within the same SLO tiers.

Spike & burst#

Spike (50→100→50 RPS) and burst (50→200→50 RPS) scenarios run as part of the periodic suite to verify graceful degradation under traffic bursts — error rate stays at 0% across the baseline range. Each baseline run ships with its spike/burst summaries alongside the raw data.

Methodology#

  • Tool: k6 v1.7.1 (Grafana), constant-arrival-rate and ramping-arrival-rate executors.
  • Scenarios: baseline (50 RPS / 5 min), spike (50→100→50 RPS), burst (50→200→50 RPS), narrow filter (30 RPS / 3 min).
  • Mix: 60% public discovery / 30% browse / 10% random + PK lookup — weighted to realistic API usage.
  • Target: production (quizbase.runriva.com), EU region. Rate limiter bypassed with an internal benchmarking key so the numbers reflect end-to-end request handling rather than the limiter. Measured client-side over the public internet.

Quarterly drift mechanism#

We re-run pnpm load:baseline + pnpm load:spike quarterly. Each run produces a fresh k6-baseline-DATE-summary.json and updates the per-endpoint x-performance block in openapi.json. If p95 regresses by more than 1.5× vs the previous run we investigate before marking the new run as the baseline (deployment, dependency upgrade, data growth, query plan change).

The lastMeasured field on every x-performance block is the date of the last successful baseline.

Raw data#

For skeptics and benchmarkers: k6-baseline-2026-05-27.json — full k6 summary metrics (p50/p90/p95/p99 per endpoint, throughput, request counts). Aggregates only.

See also#