Index templates in Elasticsearch apply the same shard settings, refresh interval, field mappings, and aliases whenever a new matching index is created. They are useful when an application owns a family of time-sliced indices and each new index must start with the same structure instead of relying on repeated create-index JSON.
Modern Elasticsearch uses composable templates through the /_index_template API. A template matches names through index_patterns, can store settings, mappings, and aliases under template, and can assemble reusable component templates with composed_of when several index families share the same blocks.
Template changes affect only indices or data stream backing indices created after the template is saved. Use application-specific patterns such as app-logs-* to avoid built-in Elastic templates, and use HTTPS plus credentials on secured clusters with a role that has the manage_index_templates cluster privilege.
$ curl --silent --show-error --fail --header "Content-Type: application/json" --request PUT "http://localhost:9200/_index_template/app-logs-template?create=true&pretty" --data '{
"index_patterns": ["app-logs-*"],
"priority": 300,
"version": 1,
"_meta": {
"description": "Defaults for application log indices"
},
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"refresh_interval": "30s"
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text" }
}
}
}
}'
{
"acknowledged" : true
}
The create=true query parameter prevents accidental replacement. Omit it only when intentionally updating an existing index template. A non-overlapping pattern such as app-logs-* avoids built-in templates; use a priority above 500 only when deliberately overriding a shared built-in or Fleet-managed pattern.
$ curl --silent --show-error --fail --request POST "http://localhost:9200/_index_template/_simulate_index/app-logs-2026.04?pretty&filter_path=template.settings.index.number_of_shards,template.settings.index.number_of_replicas,template.settings.index.refresh_interval,template.mappings.properties,overlapping"
{
"template" : {
"settings" : {
"index" : {
"refresh_interval" : "30s",
"number_of_shards" : "1",
"number_of_replicas" : "0"
}
},
"mappings" : {
"properties" : {
"level" : {
"type" : "keyword"
},
"message" : {
"type" : "text"
},
"timestamp" : {
"type" : "date"
}
}
}
},
"overlapping" : [ ]
}
Simulation returns the configuration Elasticsearch would apply without creating the index. Remove filter_path when troubleshooting overlap or merge details.
$ curl --silent --show-error --fail --request PUT "http://localhost:9200/app-logs-2026.04?pretty"
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "app-logs-2026.04"
}
Index templates apply only at index-creation time, so creating a test index proves the template can be used by new matching indices.
$ curl --silent --show-error --fail "http://localhost:9200/app-logs-2026.04/_settings?pretty&filter_path=*.settings.index.number_of_shards,*.settings.index.number_of_replicas,*.settings.index.refresh_interval"
{
"app-logs-2026.04" : {
"settings" : {
"index" : {
"refresh_interval" : "30s",
"number_of_shards" : "1",
"number_of_replicas" : "0"
}
}
}
}
Using number_of_replicas 0 keeps a one-node validation cluster green. Raise the replica count when another data node should hold a copy.
$ curl --silent --show-error --fail "http://localhost:9200/app-logs-2026.04/_mapping?pretty&filter_path=*.mappings.properties"
{
"app-logs-2026.04" : {
"mappings" : {
"properties" : {
"level" : {
"type" : "keyword"
},
"message" : {
"type" : "text"
},
"timestamp" : {
"type" : "date"
}
}
}
}
}
$ curl --silent --show-error --fail "http://localhost:9200/_index_template/app-logs-template?pretty&filter_path=index_templates.name,index_templates.index_template.index_patterns,index_templates.index_template.priority,index_templates.index_template.version,index_templates.index_template._meta,index_templates.index_template.template.settings.index.number_of_shards,index_templates.index_template.template.settings.index.number_of_replicas,index_templates.index_template.template.settings.index.refresh_interval"
{
"index_templates" : [
{
"name" : "app-logs-template",
"index_template" : {
"index_patterns" : [
"app-logs-*"
],
"template" : {
"settings" : {
"index" : {
"number_of_shards" : "1",
"number_of_replicas" : "0",
"refresh_interval" : "30s"
}
}
},
"priority" : 300,
"version" : 1,
"_meta" : {
"description" : "Defaults for application log indices"
}
}
}
]
}
$ curl --silent --show-error --fail --header "Content-Type: application/json" --request PUT "http://localhost:9200/_index_template/app-logs-template?pretty" --data '{
"index_patterns": ["app-logs-*"],
"priority": 300,
"version": 2,
"_meta": {
"description": "Defaults for application log indices"
},
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"refresh_interval": "5s"
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text" },
"service": {
"properties": {
"name": { "type": "keyword" }
}
}
}
},
"aliases": {
"app-logs-search": {}
}
}
}'
{
"acknowledged" : true
}
Updating an index template changes only future indices that match the pattern. Existing indices keep the settings, mappings, and aliases they already received at creation time.
$ curl --silent --show-error --fail --request PUT "http://localhost:9200/app-logs-2026.05?pretty"
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "app-logs-2026.05"
}
$ curl --silent --show-error --fail "http://localhost:9200/app-logs-2026.05/_settings?pretty&filter_path=*.settings.index.refresh_interval,*.settings.index.number_of_replicas"
{
"app-logs-2026.05" : {
"settings" : {
"index" : {
"refresh_interval" : "5s",
"number_of_replicas" : "0"
}
}
}
}
$ curl --silent --show-error --fail "http://localhost:9200/_alias/app-logs-search?pretty"
{
"app-logs-2026.05" : {
"aliases" : {
"app-logs-search" : { }
}
}
}
$ curl --silent --show-error --fail "http://localhost:9200/app-logs-2026.05/_mapping?pretty&filter_path=*.mappings.properties.service.properties.name"
{
"app-logs-2026.05" : {
"mappings" : {
"properties" : {
"service" : {
"properties" : {
"name" : {
"type" : "keyword"
}
}
}
}
}
}
}
The original app-logs-2026.04 index keeps the older 30s refresh interval and does not gain the new alias or service.name mapping retroactively.
$ curl --silent --show-error --fail "http://localhost:9200/_index_template/app-logs-*?pretty&filter_path=index_templates.name,index_templates.index_template.version"
{
"index_templates" : [
{
"name" : "app-logs-template",
"index_template" : {
"version" : 2
}
}
]
}
$ curl --silent --show-error --fail --request DELETE "http://localhost:9200/app-logs-2026.04?pretty"
{
"acknowledged" : true
}
Deleting an index permanently removes the documents and index-level metadata stored in it.
$ curl --silent --show-error --fail --request DELETE "http://localhost:9200/app-logs-2026.05?pretty"
{
"acknowledged" : true
}
$ curl --silent --show-error --fail --request DELETE "http://localhost:9200/_index_template/app-logs-template?pretty"
{
"acknowledged" : true
}
Deleting the template stops its defaults from applying to future indices.