Skip to content

perf(ingester): invalidate head postings cache per-label#7678

Draft
kylestang wants to merge 1 commit into
cortexproject:masterfrom
kylestang:kyle/label-counts
Draft

perf(ingester): invalidate head postings cache per-label#7678
kylestang wants to merge 1 commit into
cortexproject:masterfrom
kylestang:kyle/label-counts

Conversation

@kylestang

Copy link
Copy Markdown

The head expanded postings cache previously keyed a per-metric "seed" into the cache key, so creating or deleting any series for a metric invalidated every cached entry for that metric name, even entries whose result could not have changed.

Replace the seed with a per-(tenant, label) write counter. On series create/delete each of the series' label counts is incremented. On creation, a cache entry snapshots the counts of its matched labels and stays valid as long as at least one tracked count is unchanged. Creating or deleting a series which matches all of the tracked labels expires the cache entries.

Matchers that can match an absent label (e.g. foo!="x", foo=~".*") are excluded from the snapshot since a matching series need not carry the label, so they cannot vouch for an entry. Name-only queries fall back to the old whole-metric behaviour via the name count.

The counter array is shared across tenants and namespaced by userId; it is uint32 (8MB) and read under the existing stripe locks. Adds a reason="stale" value to the cache miss metric to distinguish count invalidation from TTL expiry.

What this PR does:

Which issue(s) this PR fixes:
Fixes #

Checklist

  • Tests updated
  • Documentation added
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]
  • docs/configuration/v1-guarantees.md updated if this PR introduces experimental flags

…er-metric

The head expanded postings cache previously keyed a per-metric "seed" into
the cache key, so creating or deleting any series for a metric invalidated
every cached entry for that metric name, even entries whose result could not
have changed.

Replace the seed with a per-(tenant, label) write counter. On series
create/delete each of the series' label counts is incremented. On creation, a cache entry
snapshots the counts of its matched labels and stays valid as
long as at least one tracked count is unchanged. Creating or deleting a series which matches
all of the tracked labels expires the cache entries.

Matchers that can match an absent label (e.g. foo!="x", foo=~".*") are
excluded from the snapshot since a matching series need not carry the label,
so they cannot vouch for an entry. Name-only queries fall back to the old
whole-metric behaviour via the __name__ count.

The counter array is shared across tenants and namespaced by userId; it is
uint32 (8MB) and read under the existing stripe locks. Adds a
reason="stale" value to the cache miss metric to distinguish count
invalidation from TTL expiry.

Signed-off-by: Kyle Stang <kylestng@amazon.com>
@kylestang kylestang force-pushed the kyle/label-counts branch from ff63b21 to fe2da16 Compare July 7, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant