// signup-burst.js — нагрузочный тест регистрации новых tenant'ов. // // Сценарий: 100 signup'ов в минуту, ramping VU от 1 до 20 и обратно. // // ВАЖНО: на stage IP-лимит rate-limiter'а — 60/мин на /api/auth/signup // и /connect/token (DefaultPerIpPerMinute=60, см. // AuthRateLimiterExtensions). Запуская 100/мин с одного IP, мы УПРЁМСЯ // в 429 — это нормальный исход теста. Метрика «процент 429» показывает, // насколько IP-лимит держит вход; метрика «латенция при <60 rps» — // чистая производительность стэка. // // Чтобы по-честному померить bootstrap БЕЗ упирания в лимит — уменьшить // до 50 RPS (через TARGET_RPM=50). import http from 'k6/http'; import { check } from 'k6'; import { Trend, Rate } from 'k6/metrics'; const BASE_URL = __ENV.BASE_URL || 'http://localhost:5081'; const TARGET_RPM = Number(__ENV.TARGET_RPM || 100); const DURATION_S = 60; const PER_SECOND = TARGET_RPM / 60; const signupTrend = new Trend('signup_duration_ms', true); const signup429 = new Rate('signup_rate_limited'); export const options = { scenarios: { signup_burst: { executor: 'constant-arrival-rate', rate: TARGET_RPM, timeUnit: '1m', duration: `${DURATION_S}s`, preAllocatedVUs: 20, maxVUs: 40, }, }, thresholds: { // Прагматичные пороги. p95 на dev-stack обычно < 1.5с для signup // (создание Organization + User + Employee + Store + RetailPoint). http_req_duration: ['p(95)<3000', 'p(99)<6000'], // 429 — допустимо, но не должно быть >50% (тогда тест не информативен). signup_rate_limited: ['rate<0.7'], }, }; export default function () { const id = `${__VU}-${__ITER}-${Date.now()}`; const email = `load-signup-${id}@example.kz`; const payload = JSON.stringify({ email, password: 'Passw0rd!', organizationName: `LoadOrg-${id}`, phone: '+77001234567', plan: null, }); const t0 = Date.now(); const res = http.post(`${BASE_URL}/api/auth/signup`, payload, { headers: { 'Content-Type': 'application/json' }, tags: { name: 'signup' }, }); signupTrend.add(Date.now() - t0); signup429.add(res.status === 429); check(res, { 'status is 2xx or 429': (r) => r.status >= 200 && r.status < 300 || r.status === 429, }); }