perf(analytics): cap slim-slice narrows query at 90 days

The `narrows` query inside `computeFromRollups` scanned the user's
full `measurements` partition without an outer `measured_at` cap
even though every aggregate FILTER inside the SELECT restricted to
7/30/90 days. On a ~450k-row tenant the cold slim slice paid ~9s
TTFB to read rows that were always aggregated to NULL.

Adding `AND m."measured_at" >= NOW() - INTERVAL '90 days'` to the
outer WHERE turns the read into an index range scan on
`(user_id, type, measured_at)` and returns bit-identical output.
Expected: ~9s -> ~0.5-1s cold, sub-50ms warm.

No schema change, no migration, no env-var change. The
`computeFromLiveAggregate` split for tenants without rollup
coverage is queued for v1.4.48.
This commit is contained in:
Marc-André Bombeck committed 2026-05-22 10:09:32 +02:00
1 parent 35a7f9700a
commit 5a0e7a97e7
3 files changed
+24 -1

No files matched your search

+10
View File
@@ -251,6 +251,15 @@ export async function computeSummariesSlice(
* Happy path — DAY buckets carry `count / min / max / mean`; a narrow
* `$queryRaw` carries only the windowed avgs + regression columns the
* buckets cannot reconstruct.
*
* v1.4.47.1 — the `narrows` query takes an outer 90-day `measured_at`
* cap so the planner does an index range scan on
* `(user_id, type, measured_at)` instead of reading every row in the
* user's measurements partition. Every FILTER expression inside the
* SELECT already restricts to 7/30/90 days, so the cap excludes only
* rows that were already being aggregated to NULL. On a power-user
* account with ~450k all-time rows this lifts the slim slice from
* ~9 s cold to ~0.5-1 s; output is bit-identical.
*/
async function computeFromRollups(userId: string): Promise<SummariesSlice> {
const [narrows, latests, dayBuckets] = await Promise.all([
@@ -302,6 +311,7 @@ async function computeFromRollups(userId: string): Promise<SummariesSlice> {
FROM measurements m
WHERE m."user_id" = ${userId}
AND m."deleted_at" IS NULL
AND m."measured_at" >= NOW() - INTERVAL '90 days'
GROUP BY m."type"
`,
prisma.$queryRaw<LatestRow[]>`