An Elasticsearch index template is a saved configuration that gets applied automatically whenever an index name matches a pattern. Templates let you define settings, mappings, and aliases once and have them apply consistently across every logs-*, metrics-*, or events-* index your application creates. Since Elasticsearch 7.8, composable index templates (_index_template) are the recommended approach; legacy templates (_template) were deprecated in the same release. The composable form supports reusable component templates, explicit priority ordering, and first-class data stream integration.
This guide covers composable templates end to end: when to use them, how priorities work, how component templates compose, integration with ILM and data streams, and what to do if you still have legacy templates lying around.
What Index Templates Do
When you create an index, Elasticsearch looks for an index template whose index_patterns match the new index name. If one matches, its settings, mappings, and aliases are merged into the request. This applies even if the create-index call did not specify them.
PUT /_index_template/logs-template
{
"index_patterns": ["logs-*"],
"priority": 100,
"template": {
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1,
"refresh_interval": "30s",
"index.lifecycle.name": "logs-30d"
},
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"level": { "type": "keyword" },
"service": { "type": "keyword" },
"message": { "type": "text" },
"trace_id": { "type": "keyword" }
}
}
}
}
Now PUT /logs-2026-05-13 will create an index with 2 shards, 1 replica, a 30-second refresh interval, the logs-30d ILM policy attached, and the mappings above. Any explicit settings or mappings in the create-index request itself take precedence over the template.
Component Templates: Reusable Building Blocks
Component templates let you factor common settings and mappings into named pieces and compose them into multiple index templates. This is the idiomatic way to keep base configuration DRY.
PUT /_component_template/base-settings
{
"template": {
"settings": {
"number_of_replicas": 1,
"refresh_interval": "30s"
}
}
}
PUT /_component_template/base-mappings
{
"template": {
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"service": { "type": "keyword" }
}
}
}
}
PUT /_index_template/logs-template
{
"index_patterns": ["logs-*"],
"composed_of": ["base-settings", "base-mappings"],
"priority": 100,
"template": {
"mappings": {
"properties": {
"level": { "type": "keyword" },
"message": { "type": "text" }
}
}
}
}
The component templates listed in composed_of are merged in order, with later entries overriding earlier ones. Anything specified directly in the index template's template block overrides what came from composed_of. The order is, from lowest to highest precedence:
- Component templates in
composed_of, left to right. - The index template's own
templateblock. - The settings, mappings, and aliases in the create-index request itself.
Priority: Which Template Wins When Multiple Match
If a new index name matches more than one template's index_patterns, the template with the highest priority wins. The lower-priority templates are ignored entirely (they are not merged with the winner). Treat priority as a tie-breaker, not a layering mechanism. If you need to layer, use component templates.
Elasticsearch built-in templates use priority: 100. Fleet-managed templates can use priorities up to 200. For your own templates, picking a number in the 100-200 range is common.
PUT /_index_template/logs-default
{
"index_patterns": ["logs-*"],
"priority": 100,
"template": { /* default settings */ }
}
PUT /_index_template/logs-critical
{
"index_patterns": ["logs-critical-*"],
"priority": 200,
"template": { /* higher-replica settings for critical workloads */ }
}
A new logs-critical-2026-05-13 index matches both patterns; only logs-critical (priority 200) is applied.
Data Streams
Index templates are required for data streams. To create a data stream, the template must declare it:
PUT /_index_template/logs-stream-template
{
"index_patterns": ["logs-stream-*"],
"data_stream": {},
"priority": 200,
"composed_of": ["base-settings", "base-mappings"],
"template": {
"settings": {
"index.lifecycle.name": "logs-30d"
}
}
}
Once the template is in place, the first write to logs-stream-app creates a data stream and its first backing index automatically. The data stream's rollover behavior inherits the conditions in the attached ILM policy.
Inspecting and Managing Templates
# List all index templates
GET /_index_template
# Look up a specific one
GET /_index_template/logs-template
# Simulate what would be applied to a given index name (without creating anything)
POST /_index_template/_simulate_index/logs-2026-05-13
# Simulate a template definition
POST /_index_template/_simulate
{
"index_patterns": ["test-*"],
"template": { /* ... */ }
}
# Delete a template
DELETE /_index_template/logs-template
The _simulate_index call is particularly useful when you suspect templates are not applying the way you think. It returns the merged configuration that Elasticsearch would actually use, including which component templates contributed which fields.
Migrating From Legacy Templates
Legacy templates (PUT /_template/<name>) were deprecated in Elasticsearch 7.8 and replaced by composable templates. They still work on 8.x and 9.x, but composable templates take precedence when both match. The migration path is straightforward:
- List existing legacy templates:
GET /_template. - For each, create a composable equivalent with
PUT /_index_template/<name>. Setpriorityhigher than any conflicting legacy template. - Verify with
POST /_index_template/_simulate_index/<test-name>. - Delete the legacy template:
DELETE /_template/<name>.
The shape of the JSON body is nearly identical; the main difference is that composable templates wrap settings, mappings, and aliases inside a template object.
Common Pitfalls
- Conflicting patterns at the same priority. Two templates with overlapping
index_patternsand the sameprioritywill be rejected. Pick distinct patterns or distinct priorities. - Forgetting to bump priority over built-ins. If you are overriding Fleet or Beats templates, those use priorities up to 200. Use a higher number.
- Putting settings in two places. Settings in
composed_ofcomponent templates and in the index template's owntemplateblock are merged, but the same setting in both is overridden by the index template. Pick one home for each setting to avoid surprises. - Not testing with
_simulate_index. Always simulate before relying on a template in production. - Mismatched mapping types between components. If component A maps
user_idaskeywordand component B maps it aslong, the merge fails with a mapper exception when the index is created, not when the template is saved.
How NeverBlink Helps With Template Hygiene
Index templates are easy to set up and easy to forget about, until a year later when half the indices in the cluster trace back to a legacy template that nobody remembers writing. NeverBlink continuously inspects Elasticsearch and OpenSearch clusters for template drift: indices that did not match the expected template, indices missing ILM coverage their template should have provided, and orphan templates whose patterns no longer match any live index. NeverBlink also surfaces oversharded templates (where a number_of_shards made sense for last year's data volume and is now overshooting). Connect your cluster to NeverBlink and stop running template audits by hand.
Frequently Asked Questions
Q: What is the difference between an index template and a component template?
An index template is what Elasticsearch matches against an incoming index name. A component template is a reusable fragment of settings, mappings, or aliases that can be referenced by name from one or more index templates via the composed_of field. Component templates alone do not apply to indices; they only take effect through an index template.
Q: Do index templates apply retroactively to existing indices?
No. Templates apply only at index creation. Existing indices keep whatever settings and mappings they were created with. To bring an existing index in line with a template, you either need to update its settings (for the subset that are dynamic settings) or reindex into a new index that picks up the template.
Q: Can two templates with overlapping patterns both contribute?
No. When multiple templates match the same index name, the one with the highest priority is applied and the others are ignored entirely. Use component templates for layering, not multiple index templates.
Q: How do I make sure my template applied to a new index?
GET /<index-name>/_settings
GET /<index-name>/_mapping
If you want to verify before creating: POST /_index_template/_simulate_index/<index-name>.
Q: Can I have a template that only sets aliases?
Yes. A template can contain any combination of settings, mappings, and aliases. An aliases-only template is useful for shared read aliases across a family of indices.
Q: Should I still use legacy templates?
No. Use composable templates (_index_template) for any new work and migrate legacy templates when you have a window for it.