# Performance Tests > **Cycle 1 update (2026-05-13)**: NFT-PERF-02 and NFT-PERF-03 (encrypted resource download, small/large file) were removed because the OTA / encrypted-resource-download endpoints (`POST /resources/get/...`) and the hardware-binding flow they depended on were reverted in cycle 1 (AZ-183 OTA revert, AZ-197 hardware removal). When OTA returns under the new architecture, perf scenarios for it must be re-derived from the new endpoints. ### NFT-PERF-01: Login Endpoint Latency **Summary**: Login endpoint responds within acceptable latency under normal load. **Traces to**: AC-1 **Metric**: Response time (p95) **Preconditions**: - System running with seed data (admin user from `e2e/db-init/99_test_seed.sql`) - 10 concurrent virtual users **Steps**: | Step | Consumer Action | Measurement | |------|----------------|-------------| | 1 | 10 VUs send POST /login for 30s | Measure p50, p95, p99 response times | **Pass criteria**: p95 latency < 500ms **Duration**: 30 seconds --- ### NFT-PERF-04: User List Endpoint Under Load **Summary**: `GET /users` responds within limits when DB has many users. **Traces to**: AC-11 > **Note**: this scenario originally referenced AC-9. Post-cycle-1, AC-9 is "Registration rejects duplicate email". The user-listing criterion is AC-11 (filter support). The thresholds below verify the listing path under volume; the filter semantics are covered by functional tests. **Metric**: Response time (p95) **Preconditions**: - Database seeded with 500 users (perf seed inserts dummy rows alongside the functional seed; see `scripts/run-performance-tests.sh`) - Caller is `admin@azaion.com` (ApiAdmin) **Steps**: | Step | Consumer Action | Measurement | |------|----------------|-------------| | 1 | 10 VUs send GET /users for 30s, sharing one cached JWT | Measure p50, p95, p99 response times | **Pass criteria**: p95 latency < 1000ms **Duration**: 30 seconds --- ## Runner Both scenarios are implemented in `scripts/perf-scenarios.js` (k6, JS) and orchestrated by `scripts/run-performance-tests.sh`. The runner spins up the SUT via `docker-compose.test.yml`, seeds 500 perf users into `test-db`, executes k6, captures the JSON summary to `e2e/test-results/perf-summary.json`, and tears down. To run locally: `./scripts/run-performance-tests.sh`. Requires `k6` (`brew install k6`) and Docker.