Repository navigation
Darling: three-tier retention (raw 4d / hourly CAGGs 21d / daily CAGGs kept) - #1623
Merged
Merged
Conversation
…Gs kept Builds the retention layer on top of the hourly CAGGs (#1621): downsample and bucketize past the raw hot window instead of dropping outright, so nothing is fully lost, just coarsened. All idempotent RUNTIME setup in TimescaleSupport, mirroring the hourly CAGGs. - query_store_stats_hourly CAGG (built ahead of a writable-QS primary; empty on a read-only replica until one is added). - Hierarchical DAILY CAGGs query_stats_daily / procedure_stats_daily, sourced from the hourly CAGGs (not raw; 2.28.1 supports CAGG-on-CAGG), 1-day refresh cadence. GROUP BY uses the explicit time_bucket('1 day', bucket) expression, NOT the bare `bucket` alias (which binds to the hourly source column under Postgres's input-column-wins rule and would group by hour, not day). - Tiered retention via add_retention_policy: raw tables 4d, hourly CAGGs 21d; the daily CAGGs get no policy (kept indefinitely). Each tier's horizon stays past the next tier's 3-day refresh start, so a drop never outruns the aggregate preserving it. Wired into DarlingWorker after the CAGG step. query_store_stats_daily is deferred until QS-hourly has real data to source from. Cold-start caveat (documented on EnsureRetentionPoliciesAsync): on an EXISTING store with raw older than the hourly CAGG has materialized, the first raw drop can remove buckets the CAGG never captured — backfill the hourly CAGGs past the raw horizon before retention runs. Fresh installs are safe automatically. Pinned by TimescaleContinuousAggregateTests (9 tests). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 23, 2026
argpna
pushed a commit
to argpna/PerformanceMonitor
that referenced
this pull request
Jul 24, 2026
Corrects the erikdarlingdata#1623 CAGG shapes so the composer can route to them (the read-routing follow-up), while the CAGGs are still empty (QS, read-only replica) or a day or two old. - query_store_stats_hourly: regrouped from query_id/plan_id to the composer's QS dims (module_name/query_hash) + execution-WEIGHTED sums (sum(avg_* * execution_count)) so the composer's weighted mean composes EXACTLY (duration_us_weighted_sum / execution_count_sum), not an avg-of-avgs. This is the shape a writable-Query-Store primary needs — QS composer panels were unroutable and the weighted mean unreconstructable as erikdarlingdata#1623 built it. - procedure_stats hourly + daily: added schema_name to the grouping (a composer dimension that had been dropped, so schema_name panels couldn't route). - DropStaleContinuousAggregatesAsync (wired before the ensure sweep): CREATE ... IF NOT EXISTS cannot ALTER a CAGG, so an existing old-shape CAGG is dropped (detected structurally: old QS still has query_id, old procedure_stats lacks schema_name) and recreated in the new shape. No-op once reshaped / on a fresh store; failure-isolated. query_stats CAGGs are unchanged. object_name-on-query_stats routing is deliberately deferred (would need sql_handle on both big CAGGs for a read-time join — bloats the tables the CAGGs exist to shrink; revisit with a retained module map if it matters). Pinned by TimescaleContinuousAggregateTests (updated for the new shapes). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Builds the retention layer on top of the hourly CAGGs ([#1621]). Instead of a flat "drop raw after N days," three tiers so nothing is ever fully lost, just coarsened. All idempotent RUNTIME setup in
TimescaleSupport, mirroring the hourly CAGGs (not a versioned migration).Tier 1 — raw, 4 days.
add_retention_policyon query_stats / procedure_stats / query_store_stats. 4d = 1 day past the hourly CAGG's own 3-day refresh window, so the raw drop never outruns the aggregate that preserves it.Tier 2 — hourly CAGGs, 21 days. Adds
query_store_stats_hourly(built now, ahead of any writable-Query-Store primary — empty on a read-only replica until one is added), plusadd_retention_policyat 21d on all three hourly CAGGs.Tier 3 — daily CAGGs, kept indefinitely.
query_stats_daily/procedure_stats_dailyas hierarchical CAGGs sourced from the hourly CAGGs (not raw — 2.28.1 supports CAGG-on-CAGG), 1-day refresh cadence. No retention policy — this is the coarsened, never-lost tier.Correctness note
The daily
GROUP BYuses the explicittime_bucket('1 day', bucket)expression, not the barebucketalias. A barebucketin GROUP BY binds to the hourly source column under Postgres's input-column-wins ambiguity rule, which would group by hour, not day. (Deviation from the literal spec SQL, for correctness.)Ordering safety
Each tier's retention horizon stays comfortably past the next tier's 3-day refresh start (4d raw vs 3d hourly refresh; 21d hourly vs 3d daily refresh), so a drop never removes history the next tier hasn't materialized.
add_retention_policyis a chunk-level DROP, so no off-hours window needed (unlike the CAGG backfill).Cold-start caveat (documented on
EnsureRetentionPoliciesAsync): on an EXISTING store holding raw older than the hourly CAGG has materialized, the first raw drop can remove buckets the CAGG never captured. Fresh installs are safe automatically (nothing is older than 4 days until the CAGG has been materializing that long). For an existing store (the field box), backfill the hourly CAGGs past the raw horizon before the retention runs — flagged in the client upgrade prompt.Deferred
query_store_stats_daily— added the same way oncequery_store_stats_hourlyhas real data from a writable primary to source from.Tests
TimescaleContinuousAggregateTests(9 pin tests): the three hourly shapes, the two hierarchical daily shapes with the explicit-time_bucketGROUP BY, the daily policy cadence, and the retention tiers/buffers. Live execution validated on DARLING01 (real 2.28.1) rather than the shared gated-live DB, to avoid cross-test interference on that suite.🤖 Generated with Claude Code