Repository navigation
Reduce publication review probes across report sizes and prepared plans - #302
Conversation
Backend unit coveragePASS · minimum combined coverage 98.00%. Tests: 10635 passed, 0 failed, 0 skipped. Source files: 367.
Unit coverage includes every backend workspace. PostgreSQL/Redis integration tests run separately. Commit: cc7d222 · HTML, JSON, XML reports and job logs · attempt 1 |
PR performance resultsCurrent PR head: Token usage benchmarkSource head: PASS — Token usage benchmark: all 12 comparisons, accounting checks and production-volume gates passed. Compared head: Before = frozen pre-fix SQL; after = application SQL at the compared head. Improvement = Query runtime — median milliseconds
Validation
Runtime gate allows up to 20% or 20 ms noise; PASS does not mean every case got faster. Writer latency is observational and has no pass/fail gate. Its samples include writer startup and reports may finish before a subsequent write completes. 30-day CPU, temporary writes and hash memory
DB CPU is the container CPU median, including concurrent ingestion; elapsed time is measured separately. Hash memory is the largest reported aggregate node, not total process memory. Temporary writes are PostgreSQL blocks from EXPLAIN. Production-volume coverage: retained history and 1/7/30-day counts
Production snapshot observed at: Production counts are the captured snapshot, not a live production benchmark. Full JSON artifact and job logs · attempt 1 Reader API performanceSource head: PR reader API performanceResult: INCONCLUSIVE 4 inconclusive · 4 within threshold. Zero request failures across all six runs. Base Three independent GitHub-hosted ARM64 runners, each measuring base and PR sequentially with alternating order and isolated resources for every sample. 16 users, completed bootstrap and 15 seconds of warmup before each full 60-second measurement, fixed journey seed 294, 1,000 synthetic articles, cache off, five PgBouncer slots. Latency comparisonAll latency values are in milliseconds; lower is better. Values are medians of three runs, with one-millisecond histogram bins.
Additional latency and throughput metricsEach cell shows base → PR. Latencies are in milliseconds.
All paired p95 samples and changesEach pair shares a validated runner. Cells show base → PR p95 (absolute and percentage change), in milliseconds. Slower/faster counts use the same strict 20% and 20 ms thresholds against that pair's own baseline.
Individual runs
How to interpret this reportRegressed / Improved: a p95 regression needs >20% and >20 ms increase in the medians and in at least two same-runner base/PR pairs. Improvements use the inverse threshold. Within threshold means the change did not meet both thresholds. Inconclusive: a within-revision p95 range >35% of its median and >20 ms is too noisy for a confident latency verdict. A material median change without two confirming pairs is also inconclusive; this does not prove unchanged performance. Inconclusive latency comparisons are non-blocking: the check passes without claiming an improvement. Confirmed regressions and test/report errors fail the PR gate. Throughput is descriptive: paced users do not measure maximum capacity. This uncached public API test does not establish production health, browser performance or worker capacity. Base and PR share a runner within each pair; three pairs use independent runners. Alternating order reduces host-assignment bias but cannot eliminate changes in host load over time. Full HTML/CSV reports and logs · attempt 1 |
Lighthouse ·
|
| Page | FCP | LCP | CLS | TBT | JS | Total |
|---|---|---|---|---|---|---|
Latest (/latest) |
1.23 s | 4.42 s | 0.001 | 467 ms | 361 KiB | 663 KiB |
Article preview (/articles/…) |
1.37 s | 5.02 s | 0.005 | 544 ms | 364 KiB | 685 KiB |
Topics (/topics) |
1.23 s | 4.02 s | 0.000 | 309 ms | 319 KiB | 471 KiB |
Sources (/sources) |
1.23 s | 4.20 s | 0.000 | 534 ms | 332 KiB | 488 KiB |
Public profile (/users/…) |
1.22 s | 2.67 s | 0.009 | 125 ms | 280 KiB | 428 KiB |
Leaderboard (/leaderboard) |
1.07 s | 2.38 s | 0.000 | 201 ms | 276 KiB | 383 KiB |
Mobile reader · Three cold loads per page · Median timings · Largest transfer size.
Needs attention
| Page | Finding | Measured | Target / limit |
|---|---|---|---|
Latest (/latest) |
4.42 s | 4.00 s | |
Latest (/latest) |
467 ms | 400 ms | |
Latest (/latest) |
361 KiB | 330 KiB | |
Latest (/latest) |
4.42 s | 2.50 s | |
Latest (/latest) |
467 ms | 200 ms | |
Article preview (/articles/…) |
544 ms | 400 ms | |
Article preview (/articles/…) |
364 KiB | 330 KiB | |
Article preview (/articles/…) |
5.02 s | 2.50 s | |
Article preview (/articles/…) |
544 ms | 200 ms | |
Topics (/topics) |
4.02 s | 4.00 s | |
Topics (/topics) |
4.02 s | 2.50 s | |
Topics (/topics) |
309 ms | 200 ms | |
Sources (/sources) |
4.20 s | 4.00 s | |
Sources (/sources) |
534 ms | 400 ms | |
Sources (/sources) |
332 KiB | 330 KiB | |
Sources (/sources) |
4.20 s | 2.50 s | |
Sources (/sources) |
534 ms | 200 ms | |
Public profile (/users/…) |
2.67 s | 2.50 s | |
Leaderboard (/leaderboard) |
201 ms | 200 ms |
Full reports and logs · cc7d222 · Attempt 1
|



What changes and why?
Publication reports repeatedly probe review indexes for every article. This change shares a narrow publication cohort and separates totals/median aggregation from autonomous classification so PostgreSQL can use semi/anti joins and first-match lookups.
The report's datetime bounds use SQLAlchemy's typed execution-time literals. This keeps cohort selectivity visible after generic prepared-plan adoption while retaining compilation caching and normal connection/server settings. Without this, warmed connections reproduced almost all of the original repeated work.
Manual precedence, inclusive per-article cutoffs, historical facts, distinct counts, empty periods, and duration semantics are preserved. Existing partial indexes remain in use.
The benchmark is covered by regression tests, confines atomic JSON output to
reports/publication, and uses fresh masked credentials for each disposable CI database. Coverage scope and quality thresholds are unchanged.Related issues
Closes #296.
Validation
Current head
cc7d222cmerges masterf9b9bfe2. The gateway conflict preserves master's response handling, headers-only declared rejection, and actual chunked placement-overflow checks. The publication query is unchanged.Merge validation passed: 225 focused backend tests, Python lint/format/types/version checks, 92 targeted gateway/body tests, web lint, and a production reader build with two real gateway fixture runs on Node 26.12.1. Hosted CI and native volume benchmarks are queued for this merge and must pass before merge. The hosted totals and measurements below record the previously validated
94676927source.94676927, including all ARM64 image checks. Sonar reports 98.4% new-code coverage, zero open issues/hotspots, and a passing quality gate. GitHub received the clean Sonar export; all four original alerts are fixed, and the SonarCloud check passes.Native ARM64 PostgreSQL 17.11 benchmarks passed on
94676927at 100,000 and 300,000 articles, with 1/7/30-day periods, concurrent ingestion, and custom/generic/warmed automatic plans. The larger fixture has 935,808 reviews and 495,000 historical analysis jobs, approximately 3.2 times the issue's estimated production article count. Every comparison preserved results, and all broad-report buffer, correlated-subplan, and temporary-data budgets passed.30-day steady-report medians and total shared-buffer accesses:
At 300,000 articles, serial backend CPU fell from 680 to 430 ms. Concurrent ingestion completed without errors; the concurrent 30-day report improved from 713.4 to 439.9 ms, and report plans generated zero WAL.
Measured tradeoffs: the 300,000-article 30-day report writes approximately 21 MiB of temporary data and reads it back, within its cohort budget. At 300,000 articles, the warmed seven-day automatic plan measured 132.0 ms versus 116.2 ms and uses more buffer accesses (272,153 versus 176,707). The steady seven-day report still improved from 134.5 to 110.1 ms; at the production-like 100,000-article size, warmed seven-day latency improved from 36.3 to 31.0 ms. Smaller historical job blobs and complete-workload limits are explicit in the evidence and reproduction guide, which records the earlier unchanged-query benchmark run.
Rollout notes
Application-only rollout and rollback; no migration, index, trigger, or database-wide planner change. After deployment, compare fresh statement-statistics deltas under matched reporting/ingestion workloads, including CPU, buffer work, temporary I/O, freshness, and ingestion health. Production was not modified or benchmarked by this PR.
Ready for review