feat: NFR-PERF-MENTION-001 — mention search latency budget #632

Open
opened 2026-05-19 23:31:35 +02:00 by marcel · 0 comments
Owner

Context

The 150 ms debounce in PersonMentionEditor.svelte (SEARCH_DEBOUNCE_MS) is currently uncited — no explicit NFR anchors it. PR #629's AC table claims "150 ms debounce per NFR" without a referenced NFR ID, which Elicit (#10926, #10962) flagged as Acceptance-Criteria-without-a-spec.

Requirement

NFR-PERF-MENTION-001: When the user pauses typing in the @mention search input, the system shall present updated results within 400 ms on a typical broadband connection (95th percentile).

The 400 ms figure follows the Doherty Threshold (interactive systems below 400 ms feel "instant"). Current debounce 150 ms + median backend p95 (~150 ms) + render ~50 ms ≈ 350 ms.

Measurement method

The latency is measured end-to-end in the Playwright @mention E2E suite (filed under #635) — from t_keystroke_stop (the last fill() / type() input event on the searchbox) to t_dropdown_render_complete (the first list option becoming visible to expect.element(...).toBeVisible()).

  • The run executes a sample of 100 representative search queries (varied length 3-30 chars, varied prefix uniqueness) against the dev/staging backend with a warmed Postgres cache.
  • The job records per-query elapsed ms and reports p50, p95, p99.
  • Backend latency contribution is observable separately in Tempo/Grafana (/api/persons span) and via Postgres pg_stat_statements — both already in the observability stack.

Failure criteria

  • CI: p95 across the 100-query sample run > 400 ms → the E2E job fails the build and the PR is blocked.
  • Production: when a release hits prod, a Grafana panel on /api/persons server-side latency plus the frontend RUM/Sentry transaction (if/when wired) alarms at p95 > 400 ms sustained for 10 min. Treated as a P2 follow-up, not a release blocker — the CI gate is the hard wall.

Out of scope

  • Backend latency tuning. Covered separately by #633 (response-shape DTO already shrinks the payload; further index optimization or query-plan work belongs there or in a follow-up).
  • Establishing CI access to a representative dataset for the 100-query sample. If the dev DB is too small to be representative, an issue to seed a synthetic 5k-person dataset for the E2E job lives downstream of #635.

Acceptance

  • NFR added to issue #380 description (or this issue treated as the canonical store).
  • PR #629 description's AC table updated to link this NFR by issue number. (done — AC-3 row links #632.)
  • When future PRs tune the debounce, they reference this NFR.
  • The 100-query Playwright timing assertion is added when #635 lands; this NFR's failure criteria are wired into the same job.

Reviewer rationale: Elicit on PR #629 comments #10926, #10962, #11058 (round 3 — measurement method + failure criteria gaps).

## Context The 150 ms debounce in `PersonMentionEditor.svelte` (`SEARCH_DEBOUNCE_MS`) is currently uncited — no explicit NFR anchors it. PR #629's AC table claims "150 ms debounce per NFR" without a referenced NFR ID, which Elicit (#10926, #10962) flagged as Acceptance-Criteria-without-a-spec. ## Requirement **NFR-PERF-MENTION-001**: When the user pauses typing in the @mention search input, the system shall present updated results within **400 ms** on a typical broadband connection (95th percentile). The 400 ms figure follows the Doherty Threshold (interactive systems below 400 ms feel "instant"). Current debounce 150 ms + median backend p95 (~150 ms) + render ~50 ms ≈ 350 ms. ## Measurement method The latency is measured end-to-end in the Playwright @mention E2E suite (filed under #635) — from `t_keystroke_stop` (the last `fill()` / `type()` input event on the searchbox) to `t_dropdown_render_complete` (the first list option becoming visible to `expect.element(...).toBeVisible()`). - The run executes a sample of **100 representative search queries** (varied length 3-30 chars, varied prefix uniqueness) against the dev/staging backend with a warmed Postgres cache. - The job records per-query elapsed ms and reports p50, p95, p99. - Backend latency contribution is observable separately in Tempo/Grafana (`/api/persons` span) and via Postgres `pg_stat_statements` — both already in the observability stack. ## Failure criteria - **CI**: p95 across the 100-query sample run > 400 ms → the E2E job fails the build and the PR is blocked. - **Production**: when a release hits prod, a Grafana panel on `/api/persons` server-side latency plus the frontend RUM/Sentry transaction (if/when wired) alarms at p95 > 400 ms sustained for 10 min. Treated as a P2 follow-up, not a release blocker — the CI gate is the hard wall. ## Out of scope - Backend latency tuning. Covered separately by #633 (response-shape DTO already shrinks the payload; further index optimization or query-plan work belongs there or in a follow-up). - Establishing CI access to a representative dataset for the 100-query sample. If the dev DB is too small to be representative, an issue to seed a synthetic 5k-person dataset for the E2E job lives downstream of #635. ## Acceptance - [ ] NFR added to issue #380 description (or this issue treated as the canonical store). - [ ] PR #629 description's AC table updated to link this NFR by issue number. *(done — AC-3 row links #632.)* - [ ] When future PRs tune the debounce, they reference this NFR. - [ ] The 100-query Playwright timing assertion is added when #635 lands; this NFR's failure criteria are wired into the same job. Reviewer rationale: Elicit on PR #629 comments #10926, #10962, #11058 (round 3 — measurement method + failure criteria gaps).
marcel added the P3-laterdocumentationfeature labels 2026-05-19 23:31:39 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#632