Dictionary Project — Performance (k6) Report (Summary)¶
Date: 2026-08-30 · k6 version: v0.54.0. This is a concise English summary — see Performans Raporu (Turkish) for the complete report with every raw metric and commentary.
Scope limitation (read first)¶
The test environment had no network access to the real MongoDB
(port 27017 was not reachable). So these k6 runs are not against
production — they target tests/performance/server/k6TestServer.ts,
which combines the real createApp() (routing/middleware/validation/
auth/rate-limiting chain, completely unchanged) with the same in-memory
fake repositories the backend's own Vitest suite already trusts.
What this measures: the real performance of routing + middleware + JWT auth + validation + business logic. What it does not measure: MongoDB I/O latency. These numbers are not production-equivalent — they are genuine, useful signal about the application code's own layer only. No SLA threshold was invented; the numbers below are reported observationally.
Smoke tests (1 VU, short) — all genuinely executed¶
All four smoke scripts (auth-smoke.js, dictionary-read.js,
dictionary-crud.js, personnel-read.js) passed with 100% checks. Two
real script bugs (not application bugs) were found and fixed during
smoke testing: a mismatched login-response shape assumption, and a
missing encodeURIComponent around a query parameter. A seed-script bug
that left 4 of 8 dictionary subgroups empty was also found and fixed.
Load test — dictionary-read.js (staged 10 → 25 → 50 VUs, 60s total)¶
24,737 requests, 411.23 req/s average. http_req_duration: avg 1.8ms,
p95 5.07ms, max 54.91ms. k6's built-in http_req_failed metric shows
97.70% — this is not a crash: the backend's own apiLimiter (300
req/60s across /api/*) saturates quickly under 25-50 concurrent VUs
and correctly returns 429. The real successful (200) throughput was
roughly 9.4 req/s — an observational note that the current
apiLimiter threshold may be low for a 50-concurrent-user load
scenario (not a formal SLA/pass-fail claim).
Stress test (observational) — dictionary-read.js (100 VUs, 30s)¶
43,533 requests, 1,434.58 req/s peak. http_req_duration: avg 1.81ms,
p95 5.25ms, max 250.96ms. No crash, connection error, or 5xx was
observed even at 100 concurrent VUs — the server stayed stable; only
the rate limiter engaged.
Login endpoint — separate, stricter rate limit (20 VUs, 15s)¶
294 requests, 18.38 req/s. Only 6.8% (20/294) of login attempts succeeded — this is expected, correct brute-force protection from the login endpoint's own stricter limiter (not a vulnerability), though it's noted as something that could affect legitimate concurrent-login experience in a high-traffic environment.
Not executed¶
A separate "load" run for personnel-read.js / dictionary-crud.js /
mixed-workload.js was not completed — the residual rate limit left
over from the preceding 100-VU stress test caused their setup() login
calls to receive 429s. Smoke-level PASS data already exists for all
three; a fresh server instance and additional time would be needed for
a dedicated load run, which time constraints did not allow. DB/CPU/
memory monitoring was not available in this environment either — marked
NOT EXECUTED, not fabricated.
Overall result¶
k6 setup ✅, all 4 smoke scripts ✅ PASS, dictionary-read load ✅ executed, auth/login load ✅ executed, personnel-read/dictionary-crud/ mixed-workload load ⚠️ NOT EXECUTED (smoke only), stress test ✅ executed (no crash/5xx, rate-limiter saturation observed), testing against production ❌ not done (forbidden, and technically impossible — no Mongo access).