---
plan: 06-03
phase: 06-performance-production-hardening
status: complete
completed_at: 2026-06-03
commits:
  - fb35f0e
  - 5a93257
self_check: PASSED
---

# Plan 06-03: Locust Load Test Implementation

## What was built

Full Locust load test for Phase 6 SLA verification (D-04, D-05, D-06).

### Files created

| File | Purpose |
|------|---------|
| `backend/requirements-dev.txt` | Dev-only deps with `locust>=2.34.0`; includes `-r requirements.txt` |
| `backend/load_tests/locustfile.py` | Full DocuVaultUser implementation (121 lines) |
| `backend/load_tests/README.md` | Operator guide: install, run command, env vars, SLA semantics, cleanup |

### Key decisions

**Credential strategy: Option A (self-bootstrapping)**
`on_start()` calls `POST /api/auth/register` (409 silently ignored), then `POST /api/auth/login`. Zero out-of-band setup; works against a clean DB.

**Upload endpoint: direct `/api/documents/upload`**
Confirmed against `backend/api/documents.py`: accepts `UploadFile file` + `Form target_backend="minio"`. Used over the presigned-URL flow (upload-url → MinIO PUT → confirm) because it is a single HTTP call from the Locust process perspective, simpler to implement correctly, and exercises the same code path for performance measurement.

**Task weights (D-05 realistic session)**
| Task | Weight | Endpoint |
|------|--------|----------|
| list_documents | 5 | GET /api/documents/ |
| get_document | 3 | GET /api/documents/{id} |
| upload_document | 2 | POST /api/documents/upload |
| refresh_token | 1 | POST /api/auth/refresh |

**SLA listener (D-06)**
`@events.quitting.add_listener check_sla` reads `stats.total.get_response_time_percentile(0.95/0.99)` and `fail_ratio`. Sets `environment.process_exit_code = 1` if: fail_ratio > 1%, p95 > 200ms, or p99 > 500ms.

## Acceptance criteria verification

- `locust` in requirements-dev.txt only (not requirements.txt): ✓
- Syntax valid (`ast.parse`): ✓
- `class DocuVaultUser`: 1 ✓
- No `raise NotImplementedError` stubs: 0 ✓
- `events.quitting.add_listener`: 1 ✓
- `@task` decorators: 4 ✓
- p95 and p99 references: present ✓
- No application code imports: 0 ✓
- README.md with LOAD_TEST_EMAIL documentation: ✓

## Notes for downstream plans

- Plan 06-06 should reference this file in the RUNBOOK.md under the "Load Testing" section
- The load test user (`loadtest@example.com`) will persist in the DB after a run — operator cleanup documented in README.md
- Locust is intentionally excluded from the production Dockerfile; the production requirements.txt is unchanged
