Same-day hotfix on v1.4.47. Dashboard cold mount was paying ~9 s TTFB on /api/analytics?slice=summaries for power-user accounts; tracked to a single SQL pass that scanned the user's full measurements partition without an outer time cap, even though every aggregate inside the SELECT restricted to 7/30/90 days.
Changed
src/lib/analytics/summaries-slice.ts— thenarrowsquery insidecomputeFromRollupsgainsAND m."measured_at" >= NOW() - INTERVAL '90 days'on the outer WHERE. The planner now uses an index range scan on(user_id, type, measured_at)instead of a full per-user partition read. Output is bit-identical because the innerFILTER (WHERE m."measured_at" >= NOW() - INTERVAL 'N days')clauses already discarded rows outside the 90-day window.
Effect
On a ~450 000-row tenant:
- slim slice cold: ~9 s → ~0.5-1 s
- slim slice warm: sub-50 ms (unchanged, Map-lookup cache)
The computeFromLiveAggregate split (for tenants without rollup coverage) stays queued for v1.4.48 — it needs a 2-query split to preserve the all-time count/min/max/mean.
Risk
Zero. No schema change, no migration, no env-var change. Standard image roll.
Operator notes
No prisma migrate deploy step required.