Elasticsearch Index Templates Explained: Legacy Templates, Composable Templates, Dynamic Templates, and ILM Best Practices

Elasticsearch index templates automatically apply settings, mappings, and aliases when new indexes are created. They solve repeated configuration, uncontrolled dynamic mapping, and the operational complexity of time-series indexes. This article covers Legacy templates, Composable Templates, dynamic templates, and ILM integration. Keywords: Elasticsearch, index templates, ILM.

Technical Specification Snapshot

Parameter Description
Technical Topic Elasticsearch Index Template
Applicable Versions Legacy: compatible with 7.x; Composable: 7.8+; Legacy was removed in 8.x
Core Language JSON / REST API
Access Protocol HTTP
Typical Scenarios Logs, metrics, events, data streams, time-series indexes
Core Dependencies Elasticsearch, optional IK analyzer, ILM
Source Platform CNBlogs technical article
Star Count Not provided in the original article

WeChat sharing prompt

AI Visual Insight: This GIF shows a social sharing prompt on a blogging platform rather than the Elasticsearch console or an index structure view. As a result, it does not contain technical state information that can be directly used for template configuration, mapping design, or ILM operations.

Elasticsearch index templates are the core mechanism for standardizing index configuration

At their core, index templates let you define the shared rules for a category of indexes in advance. As long as a new index name matches index_patterns, Elasticsearch automatically applies the predefined configuration.

Their most direct value appears in four areas: standardizing shard and replica settings, stabilizing field mappings, automatically attaching aliases, and providing an entry point for lifecycle policies. This is especially important for logging and monitoring workloads.

Production environments should always use templates

Although dynamic mapping is convenient, it can easily infer the wrong field type. Once the data structure drifts in production, queries, aggregations, and sorting can all be affected, and the cost of fixing the issue becomes high.

PUT _template/log_template_test
{
  "index_patterns": ["log-*"],
  "order": 1,
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "30s"
  },
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||epoch_millis"
      },
      "message": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      },
      "level": { "type": "keyword" },
      "service_name": { "type": "keyword" }
    }
  },
  "aliases": {
    "logs_all": {}
  }
}

This configuration creates a Legacy index template. Its primary goal is to standardize shards, mappings, and query aliases for log indexes.

Legacy index templates fit simple scenarios but are gradually leaving the mainstream

Legacy Index Templates have a flat structure and straightforward syntax, which makes them useful for quickly understanding how templates work. However, unlike the newer system, they cannot split and reuse configuration components, so maintenance costs increase as the number of templates grows.

They are still available in 7.x, but starting with 7.8 you should prioritize migration to Composable Templates. Legacy templates were removed in 8.x, so they are no longer a good choice for new projects.

Common operational tasks for Legacy templates are straightforward

# Query all Legacy templates
GET _template

# Query a specific template
GET _template/log_template_test

# Delete a template
DELETE _template/log_template_test

These commands cover querying and deleting Legacy templates and provide the most basic operational entry points.

You should verify template application by creating a new index

# Create an index that matches the template pattern
PUT log-2026.04.20

# View the final index structure
GET log-2026.04.20

This step verifies whether the template was applied automatically. Focus on checking whether settings, mappings, and aliases match expectations.

Composable index templates are the recommended approach in 7.8+

The newer template system has two layers: component templates and index templates. Component templates encapsulate reusable configuration fragments, while composable index templates match indexes and assemble those components.

This design solves a common problem: multiple business domains can share one set of settings while keeping slight field-level differences. It is also better suited to multi-tenant environments and data streams.

Component templates split reusable configuration into modular parts

PUT _component_template/settings-component-test
{
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "refresh_interval": "30s"
    }
  }
}

This component template contains only index settings, making it easy to reference from multiple index templates.

PUT _component_template/mappings-component-test
{
  "template": {
    "mappings": {
      "properties": {
        "@timestamp": { "type": "date" },
        "message": { "type": "text", "analyzer": "standard" },
        "host": { "type": "keyword" },
        "level": { "type": "keyword", "index": false }
      }
    }
  }
}

This component template defines shared field mappings and works well for multiple log index families.

Composable index templates assemble components for business indexes

PUT _index_template/logs-template-test
{
  "index_patterns": ["logs-*"],
  "priority": 200,
  "composed_of": [
    "settings-component-test",
    "mappings-component-test"
  ],
  "template": {
    "mappings": {
      "properties": {
        "error_code": { "type": "integer" }  
      }
    }
  },
  "version": 1,
  "_meta": {
    "description": "Log index template that layers shared configuration and adds business-specific fields"
  }
}

The core logic here is simple: use composed_of to reuse component templates, then use template to override or supplement business-specific fields.

Dynamic templates let you control how unknown fields are indexed

Dynamic templates do not replace explicit mappings. Instead, they define rules for fields that were not declared in advance. They are especially useful for log ingestion scenarios because they prevent string fields from being mapped by default as text + keyword multi-fields.

If an index contains a very large number of fields, dynamic templates can significantly reduce storage overhead and the risk of field explosion.

PUT _index_template/dynamic-logs-template-test
{
  "index_patterns": ["logs-*"],
  "template": {
    "mappings": {
      "dynamic_templates": [
        {
          "string_as_keyword": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        },
        {
          "env_fields": {
            "match": "env_*",
            "mapping": {
              "type": "keyword",
              "index": false
            }
          }
        }
      ],
      "properties": {
        "@timestamp": { "type": "date" }
      }
    }
  }
}

This template compresses unknown string fields into keyword and stores env_* fields without indexing them to reduce resource consumption.

Index templates and ILM together create a complete time-series governance workflow

ILM lets indexes move automatically through the Hot, Warm, Cold, Frozen, and Delete phases according to defined conditions, while index templates bind lifecycle policies to indexes that will be created in the future.

In other words, templates define what an index looks like at creation time, while ILM defines how it ages after creation. You need both to support automated operations on a logging platform.

ILM policies should be designed around rollover, cost reduction, and deletion

PUT _ilm/policy/logs_ilm_policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "set_priority": { "priority": 100 },
          "rollover": {
            "max_primary_shard_size": "50gb",
            "max_age": "7d"
          }
        }
      },
      "warm": {
        "min_age": "1d",
        "actions": {
          "readonly": {},
          "shrink": { "number_of_shards": 1 },
          "forcemerge": { "max_num_segments": 1 }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "set_priority": { "priority": 0 },
          "freeze": {}
        }
      },
      "delete": {
        "min_age": "60d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

This policy defines the full lifecycle path for log indexes, from active writes to read-only mode, archival, and eventual deletion.

Binding ILM through a component template is the best practice

PUT _component_template/logs_settings
{
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "index.lifecycle.name": "logs_ilm_policy",
      "index.lifecycle.rollover_alias": "logs-app-write"
    }
  }
}

This configuration consolidates the lifecycle policy and write alias into a settings component for consistent reuse and easier version management.

FAQ

1. How should you choose between Legacy templates and Composable Templates?

If you are still maintaining an older 7.x cluster, you can keep Legacy templates for short-term compatibility. However, as long as your environment supports 7.8+, you should prioritize Composable Templates. They support component reuse, priority management, and a clearer governance model.

2. Can dynamic templates completely replace explicit mappings?

No. Dynamic templates work best as fallback rules, while critical fields such as timestamps, IDs, monetary values, and status codes should still have explicitly declared types. This keeps query behavior stable and avoids compatibility issues caused by implicit mappings.

3. Why must ILM be used together with templates?

Because an ILM policy does not automatically attach itself to future indexes. Only when you bind it in a template through index.lifecycle.name and index.lifecycle.rollover_alias can newly created indexes automatically enter lifecycle management.

Key takeaways summarize the full Elasticsearch index template system

This article systematically explains the Elasticsearch index template ecosystem, including Legacy templates, component templates, composable index templates, dynamic templates, and ILM integration. With these mechanisms, you can standardize settings, mappings, and aliases, reduce the risks of uncontrolled dynamic mapping, and improve the maintainability of log-based time-series indexes.