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.

Steps to create component templates in Elasticsearch:

  1. Create a component template for reusable field mappings.
    $ 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.

  2. Create a component template for reusable index settings.
    $ 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
    }
  3. Create an index template that composes the component templates.
    $ 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.

  4. Retrieve the stored component templates to confirm their names, versions, and descriptions.
    $ 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"
            }
          }
        }
      ]
    }
  5. Retrieve the index template to confirm it references both component templates.
    $ 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
          }
        }
      ]
    }
  6. Simulate a matching index name to preview the merged settings and mappings before creating an index.
    $ 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.

  7. Create a test index that matches the template pattern.
    $ 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.

  8. Retrieve the test index mappings to confirm the field types.
    $ 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"
            }
          }
        }
      }
    }
  9. Retrieve the test index settings to confirm the shared defaults were applied.
    $ 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.

  10. Delete the test index after verification.
    $ curl -sS -X DELETE "http://localhost:9200/app-logs-000001?pretty"
    {
      "acknowledged" : true
    }

    Deleting an index permanently removes its data.