Skip to content

Store Checkpointer Pressure judges the average sync per checkpoint, not the interval's sum (#4037) - #4096

Merged
erikdarlingdata merged 3 commits into
devfrom
fix/4037-checkpointer-per-checkpoint-bar
Sep 24, 2026
Merged

erikdarlingdata merged 3 commits into
devfrom
fix/4037-checkpointer-per-checkpoint-bar

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

Store Checkpointer Pressure now judges the average sync time per checkpoint in the interval, not the interval's summed sync time. The old rule compared an hourly sum (about twelve timed checkpoints on the default five-minute checkpoint_timeout) against a per-checkpoint bar (CheckpointSyncBarMs, 10 s, the MCP read deadline). So a healthy store whose checkpoints each sync in five to eight seconds breached every interval and never recovered: about four alerts a day at the 360-minute cooldown on one production store, and a second store sitting on the bar.

Closes #4037

What changed

  • Schema rung V140 adds nullable collect.store_metrics.checkpoints_timed, filled on the object_kind = 'checkpointer' row only, with no default and no backfill. StorageVersion.SchemaVersion goes 139 → 140, and the viewer's schema probe recognises the new column. Fleet stores go from schema 139 (or 137) to 140 on the next install.
  • StoreSelfMetrics writes the timed count from pg_stat_checkpointer.num_timed (PostgreSQL 17+) or pg_stat_bgwriter.checkpoints_timed (older).
  • DarlingStoreMetricsReader: CheckpointerSample and CheckpointerDelta carry the timed count. CheckpointCount = timed + requested, and AverageSyncMsPerCheckpoint = sync / count. IsPressure is now requested > 0 (unchanged) or average > bar.
    • When either sample of the pair has no timed count (a row written before V140), the average arm is unmeasured. It never falls back to the old sum, so the alert can't fire from pre-rung rows.
    • An interval with zero checkpoints is not judged.
    • A timed count that goes backwards counts as a reset, like the other counters.
  • DarlingSelfAlertEvaluator: the alert message, detail, short message and recovery message state the checkpoint count and the per-checkpoint average. The stale pointers to two fixes that already shipped are removed. The served text has no issue refs.
  • get_store_metrics: the checkpointer block adds timed, cumulative_timed, checkpoint_count and average_sync_ms_per_checkpoint. No field is renamed, and sync_bar_ms stays. The reading note states the average and the count. No tool description changed.

Tests

  • StoreToastAndCheckpointerTests (67): each case pinned:

    • a healthy store (many checkpoints, a low average, a sum far past the bar) → no pressure;
    • real pressure (a high average) → pressure;
    • the requested arm;
    • zero checkpoints in the interval;
    • a pre-rung null-timed pair → average arm unmeasured.

    The column-list and SQL assertions and the four CheckpointerPressure_* message assertions are also updated.

  • New CheckpointsTimedRungTests (3) takes over the top-rung claims from PostmasterStartTimeRungTests (5), following the V138 → V139 hand-off pattern.

What was run (coordinator, on the branch head)

  • Build: clean.
  • Live PostgreSQL (TimescaleDB 2.28.1 on PostgreSQL 18, throwaway container):
    • CheckpointsTimedRungTests 3/3;
    • PostmasterStartTimeRungTests 5/5;
    • StoreSelfMetricsTests 33/33 (the insert writes the new column on PostgreSQL 18);
    • StoreToastAndCheckpointerTests 67/67;
    • QsCaptureModeRouteKnobToastRungTests 6/6.
  • Full Darling suite without a live database, on macOS: 30 failures, all in Windows-only viewer, dialog and path-convention classes (PostgresAddServerDialogTests, ViewerWaitPickerLogicTests, DarlingManagedPostgresTests, AgTopologyCardsTests and similar). None is in a class this PR touches. I did not run a dev baseline on this Mac, so CI's full run is the real check.

Not verified

  • The rule on a live production store. After the install, the alert should go quiet on a healthy store only after one full interval in which both samples carry the timed count. Until then the average arm is unmeasured, and only the requested arm can fire.
  • PostgreSQL 16-and-older pg_stat_bgwriter.checkpoints_timed against a live server. The fixture runs 18.

CHANGELOG entry

@erikdarlingdata
erikdarlingdata enabled auto-merge (squash) September 24, 2026 00:02
@erikdarlingdata
erikdarlingdata merged commit 6a26d1a into dev Sep 24, 2026
15 of 16 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/4037-checkpointer-per-checkpoint-bar branch September 24, 2026 00:36
erikdarlingdata added a commit that referenced this pull request Sep 24, 2026
* Add 48 buffered CHANGELOG entries in one splice

Adds 48 entries and 48 link refs (#4057, #4077, #4079, #4081, #4082, #4083, #4084, #4085, #4086, #4087, #4088, #4089, #4090, #4091, #4092, #4093, #4095, #4096, #4099, #4100, #4101, #4103, #4105, #4106, #4107, #4108, #4109, #4110, #4111, #4113, #4114, #4115, #4116, #4117, #4118, #4119, #4120, #4121, #4122, #4123, #4124, #4125, #4126, #4127, #4131, #4133, #4136, #4141). Each PR's entry was buffered, and this lands every entry whose PR was merged on origin/dev when it ran.

Entries found under a bare section line (none unless the old script ran again) move into the matching ### section, below the new entries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQh8LczP1HGLXQYAx4oTZC

* Changelog splice: add #4137's entry, which merged before the splice but was missed

#4137 (pg_plan_capture reads csvlog) merged at 05:57Z with a CHANGELOG entry section in its
body. It was neither spliced nor listed as needing no entry. Its entry goes under Fixed, right
after #4136's, and #4136's last sentence now points to it instead of saying plan capture is
unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUU29PuGg9TUFBsACgZg2K

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant