Skip to content

docs(investigations): consolidate findings for #1097, #1096, #1094 - #1179

Merged
vjuliaife merged 1 commit into
vjuliaife:mainfrom
Martha-code-dev:docs/investigation-followup-1097-1096-1094
Aug 29, 2026
Merged

docs(investigations): consolidate findings for #1097, #1096, #1094#1179
vjuliaife merged 1 commit into
vjuliaife:mainfrom
Martha-code-dev:docs/investigation-followup-1097-1096-1094

Conversation

@Martha-code-dev

Copy link
Copy Markdown
Contributor

Summary

closes #1097
closes #1096
closes #1094

Completes the investigation-only follow-up for the three issues PR #1173 linked as "relates to" but did not close (#1173 fixed the one issue with an actual code bug, #1095, and left #1094/#1096/#1097 as investigation-only since no code changes were warranted for them at the time — see that PR's body). Each of these three issues' acceptance criteria only asked to benchmark, measure, document, and report findings — no code fix was requested. All three were already fully investigated (findings posted as comments on each issue); this PR consolidates those findings into docs/investigations/*.md, matching the format already used for #1090 and #1093, so there's a durable doc rather than only a comment thread.

No functional code changes in this PR — docs only.

Findings

#1097GET /compliance/flags listing at 10x volume

docs/investigations/compliance-flags-listing-at-scale.md

EXPLAIN (ANALYZE, BUFFERS) at 1x (1500 flags) vs 10x (15000 flags): latency essentially flat, 1.05ms → 1.16ms. The existing composite index idx_compliance_flags_surety(surety_id, created_at DESC) already matches this query's WHERE + ORDER BY shape exactly, so Postgres never scans more than the requested page. Filtered variants (severity/resolution_status/importer_id) can only be faster, verified directly for resolution_status = 'open'. Payload size is bounded by the enforced limit <= 100. No action needed at current or 10x volume; cursor-based pagination is flagged only as a future consideration if a single surety_id ever accumulates tens of thousands of flags (OFFSET depth is the only theoretical degradation mode, and it isn't hit at these volumes).

#1096GET /compliance/dashboard aggregation cost as volume grows

docs/investigations/compliance-dashboard-aggregation-at-scale.md

Profiled all 8 cold-cache sub-queries at 1x vs 10x. All are Seq Scans (structurally unavoidable — several filter on resolution_status alone, which isn't covered by any surety_id-scoped index). Buffers scale ~linearly with table size (~10x for a ~10x row increase), confirming O(n) cost per sub-query. Worst measured case at 10x: ~12ms. Linear extrapolation to 100x suggests ~100-150ms cold-miss latency — not measured directly, disclosed as extrapolation, not a load test. The 5-minute per-admin cache TTL bounds cold-misses to at most one per admin per 5 minutes regardless of traffic, so total query load stays low regardless of hit-ratio (which isn't independently measurable without a running server — disclosed rather than guessed). No urgent action needed. Two candidate follow-ups documented for before ~50-100x volume: an incremental KYC-count summary table (reusing the importer_metrics_mv pattern already in this codebase) and a plain index on compliance_flags.resolution_status — both left as documented recommendations rather than implemented here, since their value depends on production data's actual open/resolved ratio, and a low-selectivity index that goes unused just adds write overhead for nothing (the same failure mode already documented for idx_importers_created_at in #1095/#1173).

#1094 — importers full-text search at 10x volume

docs/investigations/importers-fulltext-search-at-scale.md

Primary finding: the search feature this issue describes doesn't exist in the codebase. Migration 006_importers_fulltext_search.sql correctly added legal_name_tsv (a GENERATED ALWAYS AS (...) STORED column) and its GIN index, but no route anywhere in apps/api/src actually queries it — GET / has no search parameter at all. So "trigger-based tsvector maintenance" (per the issue's AC) doesn't apply either — it's a stored generated column, not trigger-maintained; confirmed no tsvector-related trigger fires on insert. Benchmarked the query the feature would use once built: at 10x (5000 rows), the planner correctly prefers a Seq Scan (1.02ms) over the GIN index (2.83ms when forced) for a ~4%-selectivity two-word search — expected, correct cost-based behavior, not a bug. Index size is ~40% of table size (600KB / 1.46MB), a normal ratio for GIN. Recommendation: building the actual search endpoint is a new feature, not a performance fix, so it's out of scope here — flagging it as a separate feature-issue candidate rather than bundling a new endpoint into this investigation PR.

What's not in this PR

No index or code changes are made for any of the three issues. Every investigated query already performs acceptably at 10x, and the two speculative index candidates for #1096 are documented as recommendations pending real production selectivity data, not implemented — see that doc's reasoning.

Test plan

  • Local Postgres 15, seeded at 1x and 10x per issue as described in each doc.
  • EXPLAIN (ANALYZE, BUFFERS) captured for every query analyzed; the underlying migrations (006_importers_fulltext_search.sql, the compliance-flags/dashboard indexes) were not modified.
  • No app code touched — nothing to run beyond the queries themselves.

…uliaife#1094

Adds docs/investigations/*.md for the three performance-investigation
issues left open after vjuliaife#1173, which linked them as related context but
did not close them. Consolidates the findings already posted as GitHub
comments on each issue into the same docs/investigations/ format used
for vjuliaife#1090 and vjuliaife#1093.

- compliance-flags-listing-at-scale.md (vjuliaife#1097): EXPLAIN ANALYZE at 1x/10x
  shows flat latency (1.05ms to 1.16ms); existing composite index already
  covers the query shape. No action needed.
- compliance-dashboard-aggregation-at-scale.md (vjuliaife#1096): all 8 cold-cache
  sub-queries profiled at 1x/10x; cost scales linearly with table size as
  expected for unfiltered aggregates, worst case ~12ms at 10x. No urgent
  action; two candidate indexes documented for future consideration once
  real production selectivity can be checked.
- importers-fulltext-search-at-scale.md (vjuliaife#1094): confirms the migration's
  tsvector column and GIN index are correctly built and perform well, but
  no route in the codebase actually queries them yet. The search feature
  described by the issue was never wired up. Recommends a follow-up
  feature issue rather than bundling a new endpoint into this
  investigation.
@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@Martha-code-dev Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tariff-shield-web Error Error Aug 29, 2026 2:31pm

@vjuliaife
vjuliaife merged commit f1c2467 into vjuliaife:main Aug 29, 2026
9 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants