Files
HOA_Financial_Platform/load-tests/cycle-template.md
2026-03-19 16:11:32 -04:00

3.6 KiB
Raw Blame History

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:
    // 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 (12 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)<XXX
POST /api/journal-entries p(95)<XXX
GET /api/budgets/:year/vs-actual p(95)<XXX

Claude Code update command (run after confirming fixes):

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.