[9.4] [ResponseOps] Skip unchanged alerts-as-data index templates on install (#280154) - #291097
Merged
Merged
Conversation
elastic#280154) ## Summary Extends the skip-unchanged (`_meta` content-hash) installation work from elastic#278126 to **index templates**, completing that behavior across the resource types the alerts service installs per context. elastic#278126 is merged. Previously `createOrUpdateIndexTemplate` always PUT the template on every install. Now it stamps a content hash into the template's `_meta`, GET-checks the currently-installed template, and **skips the write when the hash matches**. ## Why This is the remaining slice of Phase 2 of elastic#246016. On its own, elastic#278126 makes a repeated context install a no-op for the ILM policy and component templates, but the **index template still re-PUT** every time. Elasticsearch already recognises an identical PUT and leaves the cluster state alone, so these writes were not publishing new cluster states — but the body still crosses the wire from every node, and the master still queues and runs a cluster-state update task that parses the template before concluding nothing changed. That matters most in combination with the per-node install lock (elastic#280126): when one node installs and the others follow, a follower's install should be cheap GETs, not redundant cluster-state writes. With this change, a follower's repeated install is a no-op across component *and* index templates. ## What changed - `create_or_update_index_template.ts`: - a single `getExistingIndexTemplate` GET now returns both the existing `total_fields.limit` (for the Phase-1 preservation) and the existing `_meta.content_hash`. - the content hash is computed **after** the Phase-1 limit preservation, so the stamped hash matches the body actually installed. - skip the `putIndexTemplate` (and the preceding `simulateTemplate`) when the installed hash matches. ### Fail-safe Skipping happens only on a positive hash match. A missing stamp (templates installed before this change), a 404, or any GET failure — permissions, an exhausted retry — leaves the installed content unknown and falls through to the normal PUT, so the check can never block an install that would otherwise have succeeded. The worst case is today's behavior: a redundant write. On that fall-through path we also cannot preserve a higher existing `total_fields.limit` (same as a 404). The skip still keys off the stamp, not the live body: a hand-edited template with an intact `content_hash` stays un-repaired, where every install used to rewrite it. ### The `total_fields.limit` is tracked apart from the hash The limit is deliberately left out of the content hash. Kibana raises it outside this path while a mapping install crawls the limit up (`updateIndexTemplateFieldsLimit`), and operators raise it by hand through DevTools or the fields-limit API — both leaving `_meta` intact. Hashing it would make every such raise read as a changed template and rewrite byte-identical content on the next startup, which is exactly the write this PR exists to remove. It is compared as a number instead, and skipping requires *both* an unchanged hash and an installed limit that already satisfies the configured one, so a genuinely raised configured limit still installs and a template missing `ignore_dynamic_beyond_limit` still gets repaired: | change | before | now | | --- | --- | --- | | limit raised out of band (crawl / DevTools) | redundant install | skipped | | configured limit raised | install | install | | configured limit lowered | install (preserving the higher limit) | skipped | | anything else in the template changed | install | install | ### Logging The install is logged at `info` with the reason it went ahead (`not installed`, `installed template carries no content hash`, `content changed (<old> -> <new>)`, or an unsatisfied limit). Installs are the rare event after this change, so a resurgence of template writes is visible without enabling debug logging. The skip stays at `debug`, since at `info` it would add a line per template per (context x space) on every startup. ## Scope / not included - **Concrete write index / mapping** hash-skip and the **monotonic-version rule** are intentionally *not* here — they're separate, more involved changes (the mapping path interacts with the auto-increase retry, and version-monotonicity needs semver comparison). This PR is the index-template slice. - No change to *when* install runs or to auto-increase behavior. ## Testing - `node scripts/jest x-pack/platform/plugins/shared/alerting/server/alerts_service` — 333 pass, incl. index-template tests (stamped PUT / skip-on-match / PUT-on-stale-hash / PUT-when-unreadable) and updated integration assertions. - `node scripts/jest .../rule_registry/server/rule_data_plugin_service` — pass. - `node scripts/jest_integration --config x-pack/platform/plugins/shared/alerting/jest.integration.config.js x-pack/platform/plugins/shared/alerting/server/integration_tests/skip_unchanged_index_templates.test.ts` — 5 pass against a real Elasticsearch: the stamp/skip round trip, the re-PUT on change, the unstamped upgrade path, and both limit directions (the out-of-band raise driven through the real `updateIndexTemplateFieldsLimit`). - scoped `type_check` and `eslint` clean. Contributes to elastic#246016 --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit 49e091e)
ersin-erdal
enabled auto-merge (squash)
September 15, 2026 11:44
kibanamachine
requested review from
pmuellr
and removed request for
kibanamachine
September 15, 2026 11:45
Contributor
💚 Build Succeeded
Metrics [docs]
|
darnautov
approved these changes
Sep 15, 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.
Backport
This will backport the following commits from
mainto9.4:Questions ?
Please refer to the Backport tool documentation