Using Index Templates and Component Templates the Structured Way
AI generated
_doc
_index
Elasticsearch · OpenSearch · Mapping · Governance
Using Index Templates and Component Templates the Structured Way
consistent mappings across every time series index

Anyone who creates new indices for logs, metrics or orders every day knows the problem: without a central definition, mappings and settings drift apart until queries return inconsistent results. Composable index templates and reusable component templates solve exactly that by defining mapping rules once and applying them automatically to every new index that matches a naming pattern.

16 min read Index Templates · Component Templates · Priority Ordering Elasticsearch 8.x · OpenSearch 2.x

1. The problem index templates actually solve

An index template is a stored template that automatically applies settings, mappings and aliases to every new index whose name matches a defined pattern. Without this automation, every team that creates daily rotating indices such as logs-app-2026.07.24 has to maintain the mapping by hand or duplicate it inside application code. As soon as a field is forgotten or a data type is set incorrectly, indices belonging to the same logical data stream drift apart, and aggregations across several indices return inconsistent or faulty results.

The second problem an index template solves is reusability. Production clusters often carry dozens of index patterns with partially identical base settings such as replica count, refresh interval or analyzer definitions. Without central management, every one of these configurations gets copied multiple times, and a later change, for example a modified shard count for better performance, has to be repeated in every single template. Component templates solve this duplication problem by defining building blocks that several index templates can reference jointly.

In practice, the value of a well structured index template becomes obvious with time series data: logging pipelines, metric collectors and e-commerce order histories continuously produce new indices. Every one of these indices needs exactly the same mapping so that Kibana dashboards, alerting rules and reporting queries keep working across index boundaries. A centrally maintained template turns this consistency into a system property instead of leaving it to the discipline of individual developers.

2. Composable index templates: structure and syntax

Since Elasticsearch 7.8, composable index templates have fully replaced the old legacy templates, and OpenSearch follows the same API structure. A composable template consists of index_patterns, an optional template block with settings and mappings, and a list of referenced component templates. The index_patterns support wildcards such as logs-app-*, so every newly created index with a matching name inherits the template automatically, without an application having to ship the mapping definition itself.

The key structural difference from legacy templates is that composable index templates explicitly separate their own definition from referenced component templates. The template field inside the index template itself only holds settings that are specific to this one pattern, while shared building blocks are pulled in via composed_of. The example below shows a complete index template for application logs with its own settings and two referenced component templates.


PUT _index_template/logs-app-template
{
  "index_patterns": ["logs-app-*"],
  "priority": 200,
  "composed_of": ["logs-mappings", "logs-settings"],
  "template": {
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 1,
      "index.lifecycle.name": "logs-app-policy"
    }
  },
  "_meta": {
    "description": "Index template for all application logs",
    "owner": "platform-team",
    "managed_by": "terraform"
  }
}

The _meta field is not evaluated by Elasticsearch, but it is indispensable for the governance of an index template: it lets you document ownership, version numbers and the origin of a configuration, so a team can immediately see during debugging which system manages the template and who to contact for changes.

3. Component templates as reusable building blocks

A component template only ever contains settings or mappings, never its own index_patterns, because it is never applied directly to an index, only referenced through an index template. This separation allows shared building blocks such as a standard analyzer, a base mapping for metadata fields, or a default replica configuration to be defined once and reused across any number of index templates. If a requirement changes, for example an additional stopword list in the analyzer, a single change to the component template is enough.

In practice, a clear separation between mapping component templates and settings component templates pays off, because both evolve independently. A mapping component template for log data typically defines fields such as @timestamp, log.level and service.name that appear in every log index, while a separate settings component template governs shard count and codec compression. This modularity keeps every individual component template small and makes reviews of changes far easier.


PUT _component_template/logs-mappings
{
  "template": {
    "mappings": {
      "dynamic": "strict",
      "properties": {
        "@timestamp": { "type": "date" },
        "log.level":  { "type": "keyword" },
        "service.name": { "type": "keyword" },
        "message":    { "type": "text", "analyzer": "standard" },
        "trace.id":   { "type": "keyword" }
      }
    }
  },
  "_meta": { "description": "Base mapping for all log indices" }
}

PUT _component_template/logs-settings
{
  "template": {
    "settings": {
      "index.codec": "best_compression",
      "index.refresh_interval": "30s"
    }
  }
}

The "dynamic": "strict" parameter in the mapping component template is set deliberately: it prevents unknown fields from uncontrollably extending the mapping and forces every new field request through an explicit change to the component template. This makes mapping evolution traceable and, at the same time, guards against unintended mapping explosion, which can develop quickly under purely dynamic mapping.

4. Priority ordering and template resolution

When multiple index templates could match the same index name, the priority field alone decides which one wins: Elasticsearch selects exactly one index template with the highest priority out of all matching candidates when the index is created, there is no merging of several index templates. This differs fundamentally from component templates, whose content is merged additively inside a chosen index template, in the order they appear in composed_of.

A proven convention is to define generic templates with a low priority, for example 100, for broad patterns such as logs-*, and more specific templates with a higher priority, for example 200 or 300, for narrower patterns such as logs-app-checkout-*. That way a checkout log index automatically inherits the more specific mapping, while every other log index falls back to the generic template. If priority is missing entirely, 0 is assumed implicitly, which quickly leads to unpredictable behavior once multiple templates compete.

Within a chosen index template, the referenced component templates are merged in the order they are listed, and later entries in composed_of can override fields defined earlier. The explicit template field inside the index template itself always has the highest priority and overrides values coming from any component template. This deterministic merge order is why a cleanly structured index template guarantees predictable behavior even when a cluster manages hundreds of templates.

5. Dynamic templates inside the mapping layer

Besides index templates, which take effect before an index is created, there are dynamic templates, defined inside an already existing mapping, that govern how new, previously unknown fields get typed. A dynamic template inside an index template reacts to name patterns or detected value types and automatically assigns the matching Elasticsearch data type, for example typing every field with the suffix _ip as ip instead of the generic text.

The practical benefit is that a single mapping component template can react flexibly to variable field structures without needing an explicit definition for every possible field. This matters especially for log data with structured JSON payloads whose exact field set differs between services. At the same time, combining "dynamic": "strict" at the top level with targeted dynamic templates for known patterns prevents completely arbitrary fields from entering the mapping unchecked.


PUT _component_template/logs-mappings
{
  "template": {
    "mappings": {
      "dynamic_templates": [
        {
          "ip_fields": {
            "match": "*_ip",
            "mapping": { "type": "ip" }
          }
        },
        {
          "strings_as_keyword": {
            "match_mapping_type": "string",
            "match": "*.id",
            "mapping": { "type": "keyword" }
          }
        }
      ],
      "properties": {
        "@timestamp": { "type": "date" }
      }
    }
  }
}

6. Versioning and migrating templates

An often underestimated detail when maintaining index templates is versioning. Both index templates and component templates support a numeric version field that does not factor into mapping logic but is used as proof of which configuration is currently active. Automation tools such as Terraform or custom deployment scripts check this field to decide whether an update is needed, without comparing the full template content.

When changing an existing component template, keep in mind that the change only takes effect for newly created indices, existing indices retain their original mapping. This means a migration runs in two steps: first the template is updated, then existing indices must be moved to the new structure through reindexing or a rollover. Anyone who forgets this second step ends up with inconsistent mappings within the same logical data stream, even though the template was updated correctly.

7. Templates for time series data and data streams

For time series workloads such as logs and metrics, data streams are the logical evolution of the classic index rotation pattern, and they strictly require an index template with an enabled data_stream block. A data stream internally manages several backing indices, rotates them automatically by size or age, and exposes a single logical name for write and read operations to the outside. The index template controlling a data stream must contain an @timestamp field of type date in its mapping.

The advantage over manual index rotation with daily index names is that applications never need to know the concrete backing index, they always write against the data stream name. The index template centrally governs how often rotation happens and which ILM policy handles rollover and deletion, while component templates keep supplying the mapping building blocks. This combination makes time series indexing considerably more robust than hand built daily index scripts.


PUT _index_template/logs-app-datastream
{
  "index_patterns": ["logs-app-*"],
  "data_stream": {},
  "priority": 200,
  "composed_of": ["logs-mappings", "logs-settings"],
  "template": {
    "settings": { "index.lifecycle.name": "logs-app-policy" }
  }
}

8. Testing and validation with the simulate API

Before a new or changed index template goes to production, it should be tested against the simulate API. The endpoint _index_template/_simulate_index/<name> calculates the final mapping and settings an index with this name would actually receive, without creating the index at all. This surfaces conflicts between competing templates before they cause unexpected mappings in production.

Equally important is the endpoint _index_template/_simulate, which lets you test a template object that has not even been saved yet, before applying it via PUT. In CI pipelines this step is typically automated before every deployment, so a broken index template never reaches the production environment untested.


# Simulate resolution against an already registered template
curl -s -X POST "https://es.mironsoft.de:9200/_index_template/_simulate_index/logs-app-checkout-2026.07.24" \
  -H "Content-Type: application/json" | jq '.template.mappings'

# Simulate a not-yet-saved template definition before applying it
curl -s -X POST "https://es.mironsoft.de:9200/_index_template/_simulate" \
  -H "Content-Type: application/json" \
  -d @new-template-candidate.json | jq '.template'

9. Governance: templates in CI/CD pipelines

In teams with several developers, an index template maintained manually through the Kibana console quickly becomes a source of errors, because changes are not traceable and nobody knows the current source of truth. The proven solution is to version all index templates and component templates as code in a repository, for example as Terraform resources or as JSON files applied through a deployment script. Every change then goes through code review, gets tested against the simulate API, and is only applied to the cluster afterward through a CI pipeline.

Traceability also means that the _meta field of every component template should hold the Git commit hash or the pipeline run ID it was deployed from. That lets you immediately trace a mapping problem in production back to the change that produced the current configuration, without manually reconstructing the history in Kibana. This governance discipline scales far better than ad hoc changes through the console, especially when several teams share the same cluster with different index patterns.

An additional benefit of this practice: comparing two templates, for example between staging and production, becomes a simple diff of two JSON files in the repository instead of a tedious manual comparison over the REST API. Treating index templates consistently as code reduces configuration drift between environments to nearly zero.

Aspect Legacy Template Index Template Component Template
Applied directly to an index Yes Yes No, only referenced
Merge behavior on conflict Additive by order, unclear One winner by priority Additive by composed_of
Data streams supported No Yes Only as a building block
Reusability Low, lots of duplication Medium High, central building block
Testable via simulate API No Yes Yes, indirectly

Mironsoft

Elasticsearch operations, mapping governance and search infrastructure

Want mappings that stay consistent across hundreds of indices?

We restructure existing Elasticsearch clusters with clean index templates and component templates, set up simulate tests inside your CI pipeline, and bring governance to grown template landscapes.

Template Audit

Identify existing legacy templates and migrate them to composable templates

Component Design

Design reusable mapping and settings building blocks for your data stream

CI Integration

Wire simulate API tests and template as code into your deployment pipeline

10. Summary

Composable index templates and reusable component templates solve the fundamental problem of mapping consistency across time series indices. An index template defines which pattern receives which settings, mappings and data stream configuration, while component templates supply the actual building blocks and can be reused many times over. Priority ordering deterministically decides which index template wins among several matching candidates, while referenced component templates are merged additively.

Anyone who consistently versions index templates as code, tests them against the simulate API, and rolls them out through CI pipelines prevents configuration drift between environments and makes every mapping change traceable. Especially for time series workloads built on data streams, a clean template setup is not a nicety, it is a prerequisite for reliable dashboards, alerts and reports across every backing index.

Index Templates and Component Templates: The Essentials at a Glance

Composable Index Templates

index_patterns, priority and composed_of control which template is applied to a new index.

Component Templates

Reusable mapping and settings building blocks, never applied directly to an index.

Priority Ordering

Among competing index templates, exactly one wins, the one with the highest priority.

Simulate API

_index_template/_simulate tests the final mapping resolution before an index is created.

11. FAQ: Index Templates and Component Templates

1Index template vs. component template?
Index templates are applied directly to new indices. Component templates are building blocks only pulled in through composed_of.
2Multiple matching index templates?
Exactly one template wins, the one with the highest priority. Component templates inside the chosen template are merged additively.
3Effect on existing indices?
None. Only newly created indices inherit the change. Existing indices need reindexing or rollover.
4What is the simulate API for?
Calculates the final mapping for an index name without creating it, and surfaces conflicts before deployment.
5Index templates for data streams?
Yes, with a data_stream block and an @timestamp field of type date in the mapping.
6Preventing mapping explosion?
dynamic: strict plus targeted dynamic_templates only let known field patterns be typed automatically.
7Still use legacy templates?
No, they are deprecated and do not fully support data streams or the simulate API.
8Versioning templates sensibly?
Via the version field and _meta with Git commit hash or pipeline run ID for traceability.
9Recommended priority convention?
Low priority for broad patterns, higher priority for narrower patterns, so they win in case of conflict.
10Bringing templates into CI/CD?
Version them as code in the repository, test with the simulate API, and apply automatically through the pipeline.