PropFlowAI · latency investigation · 2026-07-25

Every number here was measured. Several of the ones we started with were not.

A 62-finding audit produced a plan. Building an instrument to check it found that the plan's two highest-ranked items were already fixed — and that the single biggest real win was one nobody had ranked first.

119 17 DynamoDB GSI1 queries per unscoped computeDashboardStats() at 17 properties. The OCCUPANCY# partition was being swept seven times per request.

Method

Counts, not milliseconds

Production latency swings ±300 ms run to run — larger than most of the wins being chased, which is why several previously-shipped optimizations were never provable end-to-end. Request counts are deterministic: the same journey over the same data issues the same requests every time.

A harness drives seven real user journeys through the real app and counts what the browser asked for and what the server actually read. Three identical baseline runs establish a noise band first — 12 of 16 steps were bit-stable; the other four are bimodal and can carry no claim at all. Only stable steps appear below.

An earlier version of this table looked convincing and was wrong. Four independent fixes each showed +6 on the same step — four different changes cannot produce an identical delta. The baseline was the anomaly, not the fixes. That is what the repeat runs are for.

Measured

The occupancy sweep

Two of the seven sweeps were self-inflicted inside one function: it listed occupancies to build the tenant set, then listed them again to filter it — on rows that already carried the status.

Per propertysweeps of OCCUPANCY#
71
Prod scaleGSI1 queries, 17 properties
11917
Prospects cold entryserver-component DDB calls
827512−315
Whole journey suiteserver-component DDB calls
964657−32%

The 827 figure was identical across all three baseline runs — 827, 827, 827. A −315 move on a column with zero variance is the cleanest signal in the whole investigation. Dashboard output was verified byte-identical against production before and after, captured back-to-back to avoid live-data drift.

Measured

Four fixes, ranked by what they actually moved

Browser request counts across the journey suite. Anything that measured zero was not shipped — the point of the instrument is to make that decision on evidence rather than on how plausible the fix sounded.

Journey step Base Poll gating Picker seed Entry contract Poll substrate
Dashboard cold entry1414131414
Work-order list cold entry1210111112
Conversations cold entry99899
Open conversation drawer00002
Prospects cold entry1513141315
Back to prospects101010109
Refocus after idle tab84888
Cold deep-link to detail1311121213
Net across the suite −10−5−4−1

Poll gating is the largest — the heavy dashboard stats poll was mounted in the operations layout, so every page re-ran it every 30 seconds whether or not a single stat was on screen.

The picker seed is the most trustworthy, despite being half the size: a clean −1 on every cold page entry, exactly the predicted mechanism. When a measurement matches the mechanism that precisely, it isn't noise.

Poll substrate was not shipped. It measured −1 and produced a +2 on drawer-open — a step that read 0, 0, 0 across three baselines, so the rise is outside the band and unexplained. Its abort-handling work fixes a real correctness bug, so it gets re-scoped rather than dropped.

Refuted

What the instrument disproved

The audit was performed against a checkout that was behind main. Re-validating all 62 findings against fresh origin/main removed several of its largest items.

The #1-ranked finding was already fixed

A full-table scan on tenant lookup — independently ranked first by a second reviewer — is now an org-bounded fan-out of point queries. The code comment records the old 11–13 second production timings as historical.

So was the plan's own top bet

The single-entry cache said to be evicting itself on every request is a 50-entry LRU with in-flight coalescing. Confirmed independently by three separate verification passes.

The thesis was wrong about how navigation works

“Every back navigation is a cold start” does not hold: browser back/forward is served from a client cache that bypasses staleness entirely. The proposed config change helps only in-app link-shaped returns — not the gesture that was measured.

And one claim of ours was wrong too

A read measured at ~574 ms returning zero rows was called dead code with “no writers anywhere.” An agent tasked with deleting it refused: the development backend holds 2,796 seeded rows, six committed tests assert non-empty results, and two live writers exist. That is a prod-data fact, not a code fact — a product gap, not dead code. No change was made.

Every fix brief carried an instruction to try to refute its own premise first. That instruction is the only reason the last item above didn't ship as a deletion.

Measured

Also fixed, on correctness grounds

A portfolio-wide, serial, write-capable pass was running on the turnovers list read path — on the server render and again on every five-second poll. Opening the page could mint records; two operators polling raced the same writes; read latency was coupled to write throughput.

It now fires once at the renewal decline that triggers it. Deleting it outright would have lost data — a terminal record can never re-enter the new path — so the orphaned cohort is closed by a one-shot backfill, dry-run by default, still awaiting a production dry-run before it is applied.

Status

Open for review

ChangeMeasured resultState
Journey harness + attribution rigthe instrument#4550
Dashboard poll gating−10 requests#4551
Property picker trusts its seed−5 requests#4552
One occupancy sweep, not seven119 → 17 queries#4567
Turnover write off the read pathcorrectness#4570
Appliance read removalpremise refutedno change

What it cost

The measurement was worth more than the fixes

Four parallel agents produced −20 requests across the suite, one unshipped regression, and one branch that did nothing on these journeys. The occupancy work — which no one had ranked first — produced a 7× reduction on the hottest read in the application.

The instrument also caught three errors that reasoning alone did not: a module-registry split that silently reported zero, a metric unstable enough to make a randomly-failing gate, and the bimodal steps behind a confident-looking table that was already half-believed.

Still unmeasured: what a real operator experiences in production. This harness proves relative improvement against a fixed dataset — it cannot speak for real traffic, and the test configuration blocks production by design. That gap needs real-user monitoring, which does not exist yet.

PropFlow Docs