# Audric Load Test Results — 2026-04-28 22:39

**Target:** https://audric.ai (production)
**VU scale:** 0.1× (10% of spec VU counts — local MacBook run)
**Engine version:** @t2000/engine v0.56.0
**k6 version:** v1.7.1

---

## Summary

| Scenario | Status | Requests | p95 Latency | Error Rate | Key finding |
|---|---|---|---|---|---|
| S1 — Steady read (100→500 VU) | ⏭️ Blocked | — | — | — | Session limit hit on test account (429). Re-run with a fresh test account or after 24h window rolls. |
| S2 — Viral address burst (200 VU) | ✅ **PASSED** | 23,447 | **24ms** | **0%** | 100% cache hit rate — ~1 BV call/min regardless of concurrency |
| S3 — Mixed read+write (200 VU) | ⏭️ Skipped | — | — | — | Requires session quota (same limit as S1) |
| S4 — BV degradation (200 VU) | ✅ **PASSED** | 23,772 | **28ms** | **0%** | 65 degraded BV responses — all 100% served from sticky-positive cache |
| S5 — Cron overlap | ⏭️ Skipped | — | — | — | Requires INTERNAL_KEY |

---

## S2 — Viral address burst (PR 1+2 cache validation)

**Setup:** 20 concurrent VUs all requesting `/api/portfolio?address=0xe1c0...f177` (same wallet). 2.5 min run. 23,447 total requests.

| Metric | Result | Spec threshold |
|---|---|---|
| p95 portfolio latency | **24ms** | < 3,000ms ✅ |
| p99 portfolio latency | ~35ms | — |
| Cache hit rate | **100.0%** | higher = better ✅ |
| Estimated BV calls/min | **~1** | < 50/min ✅ |
| HTTP error rate | **0.00%** | < 1% ✅ |
| Total requests served | **23,447** | — |

**What this proves:**

Without Upstash wallet cache (PR 1) + cross-instance fetch lock (PR 2), 20 concurrent users hitting the same address would trigger ≥20 simultaneous BlockVision API calls per cache miss — hundreds per minute at scale. With the cache:
- All 23,447 requests returned in < 25ms p95 (served from Redis, not BV)
- BlockVision was only called ~once per cache TTL across all concurrent users
- Zero errors across the entire 2.5 min burst

**Extrapolated to 200 VU (full spec):** The protection scales linearly — still ~1 BV call/min per address per TTL regardless of how many users hit the same address. This is the core DAU-scaling invariant.

---

## S4 — BlockVision degradation (PR 1 sticky-positive cache validation)

**Setup:** 20 concurrent VUs hitting `/api/portfolio` for 10.5 minutes. BV was under natural production load — 65 responses returned a degraded/partial defi source.

| Metric | Result | Spec threshold |
|---|---|---|
| p95 latency (any path) | **28ms** | < 5,000ms ✅ |
| Sticky-positive served | **100.0%** | > 80% ✅ |
| Degraded responses | **65** | expected under real prod load |
| HTTP error rate | **0.00%** | < 5% ✅ |
| Total requests served | **23,772** | — |

**What this proves:**

In 10.5 minutes of production load, BlockVision returned 65 degraded/partial responses. Every single one still returned a positive `walletValueUsd` to the user — served from the sticky-positive Upstash cache (PR 1). The cache writes a "last known good" value on every successful BV response and never overwrites with zero on degradation. This means users never see `$0` portfolio during a BV blip.

---

## Outstanding scenarios

| Scenario | How to run |
|---|---|
| **S1 (chat steady load)** | Create a fresh Audric test account → grab new JWT → `./loadtest/run.sh s1` |
| **S3 (mixed read+write)** | Same — needs fresh session quota on a new test account |
| **S5 (cron overlap)** | Need `INTERNAL_KEY` from Vercel env → `./loadtest/run.sh s5` |

---

## Acceptance criteria from spec

- [ ] S1 p95 < 4s at full 500 VU (pending: session limit on test account)
- [x] **BV CB has not opened (no `cb_open` signals in 23K+ portfolio requests)**
- [x] **S2: p95 portfolio latency 24ms at 20 VU concurrent (same address)**
- [x] **S4: 100% sticky-positive cache served under real BV degradation**
- [ ] S3 write turns always yield `pending_action` (pending: session quota)
- [ ] S5 cron shards < 60s (pending: INTERNAL_KEY)

*Generated by `loadtest/run.sh` — [Audric scaling spec PR 6](../audric-scaling-spec.md)*
