Component templates keep recurring Elasticsearch mappings, settings, and aliases in one reusable definition instead of repeating the same JSON across multiple index templates. Reusing those building blocks reduces mapping drift, keeps defaults consistent, and makes template changes easier to review.
Composable templates split responsibility between two layers. Component templates hold reusable settings, mappings, or aliases, while an index template matches index_patterns and assembles those components through composed_of when a new index or data stream is created. When multiple component templates are listed, later components override earlier ones for conflicting definitions, while settings or mappings defined directly in the index template override the component templates.
Component template changes affect only indices or data streams created after the change, so existing indices keep their current configuration until they are reindexed or updated separately. Avoid broad patterns that collide with built-in templates, and expect security-enabled clusters to require authentication, HTTPS, and the manage_index_templates cluster privilege before template APIs succeed.
$ curl -sS -H "Content-Type: application/json" -X PUT "http://localhost:9200/_component_template/app-logs-mappings?pretty" -d '{
"template": {
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text" }
}
}
},
"version": 1,
"_meta": {
"description": "Shared field mappings for application logs"
}
}'
{
"acknowledged" : true
}
Security-enabled clusters usually need either an Authorization header or --user credentials on the normal HTTPS endpoint used by operators for that cluster.
$ curl -sS -H "Content-Type: application/json" -X PUT "http://localhost:9200/_component_template/app-logs-settings?pretty" -d '{
"template": {
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 1,
"refresh_interval": "30s"
}
}
},
"version": 1,
"_meta": {
"description": "Shared index settings for application logs"
}
}'
{
"acknowledged" : true
}
$ curl -sS -H "Content-Type: application/json" -X PUT "http://localhost:9200/_index_template/app-logs-template?pretty" -d '{
"index_patterns": ["app-logs-*"],
"composed_of": ["app-logs-settings", "app-logs-mappings"],
"priority": 200,
"version": 1,
"_meta": {
"description": "Applies shared application log settings and mappings"
}
}'
{
"acknowledged" : true
}
The highest-priority matching index template wins, so keep index_patterns specific enough to avoid unintentional overlap with other templates or built-in patterns.
$ curl -sS "http://localhost:9200/_component_template/app-logs-*?pretty&filter_path=component_templates.name,component_templates.component_template.version,component_templates.component_template._meta.description"
{
"component_templates" : [
{
"name" : "app-logs-mappings",
"component_template" : {
"version" : 1,
"_meta" : {
"description" : "Shared field mappings for application logs"
}
}
},
{
"name" : "app-logs-settings",
"component_template" : {
"version" : 1,
"_meta" : {
"description" : "Shared index settings for application logs"
}
}
}
]
}
$ curl -sS "http://localhost:9200/_index_template/app-logs-template?pretty&filter_path=index_templates.name,index_templates.index_template.index_patterns,index_templates.index_template.composed_of,index_templates.index_template.priority,index_templates.index_template.version"
{
"index_templates" : [
{
"name" : "app-logs-template",
"index_template" : {
"index_patterns" : [
"app-logs-*"
],
"composed_of" : [
"app-logs-settings",
"app-logs-mappings"
],
"priority" : 200,
"version" : 1
}
}
]
}
$ curl -sS -X POST "http://localhost:9200/_index_template/_simulate_index/app-logs-000001?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" : "1"
}
},
"mappings" : {
"properties" : {
"@timestamp" : {
"type" : "date"
},
"level" : {
"type" : "keyword"
},
"message" : {
"type" : "text"
}
}
}
},
"overlapping" : [ ]
}
Simulation shows the resolved configuration without creating an index, which is the fastest way to catch missing components or overlapping templates.
$ curl -sS -X PUT "http://localhost:9200/app-logs-000001?pretty"
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "app-logs-000001"
}
Creating a real index verifies that the component templates and the index template apply together at index-creation time.
$ curl -sS "http://localhost:9200/app-logs-000001/_mapping?pretty&filter_path=*.mappings.properties"
{
"app-logs-000001" : {
"mappings" : {
"properties" : {
"@timestamp" : {
"type" : "date"
},
"level" : {
"type" : "keyword"
},
"message" : {
"type" : "text"
}
}
}
}
}
$ curl -sS "http://localhost:9200/app-logs-000001/_settings?pretty&filter_path=*.settings.index.number_of_shards,*.settings.index.number_of_replicas,*.settings.index.refresh_interval,*.settings.index.routing.allocation.include._tier_preference"
{
"app-logs-000001" : {
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"refresh_interval" : "30s",
"number_of_shards" : "1",
"number_of_replicas" : "1"
}
}
}
}
Elasticsearch can add cluster-managed defaults such as index.routing.allocation.include._tier_preference on top of the settings defined in the component template.
$ curl -sS -X DELETE "http://localhost:9200/app-logs-000001?pretty"
{
"acknowledged" : true
}
Deleting an index permanently removes its data.