# HOALedgerIQ – Load Test Improvement Report **Cycle:** 001 **Date:** YYYY-MM-DD **Test window:** HH:MM – HH:MM UTC **Environments:** Staging (`staging.hoaledgeriq.com`) **Scenarios run:** `auth-dashboard-flow.js` + `crud-flow.js` **Peak VUs:** 200 (dashboard) / 100 (CRUD) **New Relic app:** `HOALedgerIQ_App` --- ## Executive Summary > _[One paragraph: what load the system handled, what broke first, at what VU threshold, and the estimated user-facing impact. Written by Claude Code from New Relic data.]_ **Threshold breaches this cycle:** | Metric | Target | Actual | Status | |--------|--------|--------|--------| | login p95 | < 300ms | — | 🔴 / 🟢 | | dashboard p95 | < 1000ms | — | 🔴 / 🟢 | | budget vs-actual p95 | < 1000ms | — | 🔴 / 🟢 | | journal entry write p95 | < 1200ms | — | 🔴 / 🟢 | | error rate | < 1% | — | 🔴 / 🟢 | --- ## Findings ### 🔴 P0 – Fix Before Next Deploy #### Finding 001 – [Short title] - **Symptom:** _e.g., `GET /api/reports/cash-flow-forecast` p95 = 3,400ms at 100 VUs_ - **New Relic evidence:** _e.g., DatastoreSegment shows 47 sequential DB calls per request_ - **Root cause hypothesis:** _e.g., N+1 on `reserve_components` — each component triggers a separate `SELECT` for `monthly_actuals`_ - **File:** `backend/src/modules/reports/cash-flow.service.ts:83` - **Recommended fix:** ```typescript // BEFORE – N+1: one query per component for (const component of components) { const actuals = await this.actualsRepo.findBy({ componentId: component.id }); } // AFTER – batch load with WHERE IN const actuals = await this.actualsRepo.findBy({ componentId: In(components.map(c => c.id)) }); ``` - **Expected improvement:** ~70% latency reduction on this endpoint - **Effort:** Low (1–2 hours) --- ### 🟠 P1 – Fix Within This Sprint #### Finding 002 – [Short title] - **Symptom:** - **New Relic evidence:** - **Root cause hypothesis:** - **File:** - **Recommended fix:** - **Expected improvement:** - **Effort:** #### Finding 003 – [Short title] - _(same structure)_ --- ### 🟡 P2 – Backlog #### Finding 004 – [Short title] - **Symptom:** - **Root cause hypothesis:** - **Recommended fix:** - **Effort:** --- ## Regression Net — Re-Test Criteria After implementing P0 + P1 fixes, the next BlazeMeter run must pass these gates before merging to staging: | Endpoint | Previous p95 | Target p95 | k6 Threshold | |----------|-------------|------------|-------------| | `GET /api/reports/cash-flow-forecast` | — | — | `p(95) **Claude Code update command (run after confirming fixes):** > ```bash > claude "Update load-tests/analysis/baseline.json with the p95 values from > load-tests/reports/cycle-001.md findings. Tighten the k6 thresholds in > load-tests/config/environments.json staging block to match. Do not loosen > any threshold that already passes." > ``` --- ## Baseline Delta | Endpoint | Cycle 000 p95 | Cycle 001 p95 | Δ | |----------|--------------|--------------|---| | _(populated after first run)_ | — | — | — | --- ## Notes & Observations - _Any anomalies, flaky tests, or infrastructure events during the run_ - _Redis / BullMQ queue depth observations_ - _Rate limiter (Throttler) trip count — if >0, note which endpoints and at what VU count_ - _TenantMiddleware cache hit rate (if observable via New Relic custom attributes)_ --- _Generated by Claude Code. Source data in `load-tests/analysis/raw/`. Next cycle target: implement P0+P1, re-run at same peak VUs, update baselines._