Elasticsearch Dynamic Mapping: Settings, Behavior, and Best Practices

Dynamic mapping is Elasticsearch's automatic field detection: when a document arrives with a field that's not yet in the index mapping, Elasticsearch infers the field type and adds it. The behavior is controlled by the dynamic index-level setting, which accepts four values: true (the default), false, strict, and runtime. Dynamic mapping is convenient for prototyping but a frequent cause of mapping explosion, wrong-type inferences, and silent indexing failures in production.

How Dynamic Mapping Decides Field Types

When dynamic mapping is enabled, Elasticsearch inspects the JSON value and picks a type based on a fixed rule set:

JSON value Inferred Elasticsearch type
true / false boolean
Whole number long
Number with decimal float
String matching strict_date_optional_time or yyyy/MM/dd HH:mm:ss||yyyy/MM/dd (when date detection is on) date
String matching a numeric pattern (when numeric_detection is on) long or float
Other strings text with a keyword sub-field at .keyword (ignore_above: 256)
JSON object object (nested fields recursed)
Array Type of first non-null element; arrays must be homogeneous

date_detection is enabled by default. numeric_detection is off by default - turn it on per-index if your data sends numbers as strings.

The dynamic Setting Values

Value New field encountered Stored in _source Indexed/searchable
true (default) Mapping is updated, field added Yes Yes
false Mapping unchanged, field ignored Yes No
strict Indexing fails with strict_dynamic_mapping_exception n/a n/a
runtime Added as a runtime field, computed at query time Yes At query time only

The setting applies hierarchically - you can set it per-object as well as on the root mapping. A common pattern: strict at the root, but true on a specific sub-object that legitimately holds arbitrary user attributes.

Change it on an existing index:

PUT /my-index/_mapping
{
  "dynamic": "strict"
}

Why Dynamic Mapping Is Risky in Production

Three failure modes show up repeatedly:

  1. Mapping explosion. Highly variable JSON (user-provided tags, free-form attributes, error payloads) generates hundreds of unique fields. Once the field count crosses index.mapping.total_fields.limit (default 1000), new indexing requests are rejected.
  2. Wrong type inference on first document. If the first document carries "price": "19" (a string) the field gets text+keyword. Subsequent documents with "price": 19.99 (a number) either fail or coerce silently. Type is set by the first document, not the most common shape.
  3. Cluster-state churn. Every new field is a cluster-state update broadcast to every node. A burst of new fields can stall master-side processing and back up _cluster/pending_tasks.

The default dynamic: true is fine for development. For production indices, strict or false with explicit field additions via the Update Mapping API is the safer pattern.

Dynamic Templates: Controlled Auto-Mapping

When you want some fields auto-mapped but with predictable types, use dynamic templates. They match new fields by name pattern or detected type and apply a specific mapping:

PUT /events
{
  "mappings": {
    "dynamic_templates": [
      {
        "ids_as_keyword": {
          "match":   "*_id",
          "mapping": { "type": "keyword" }
        }
      },
      {
        "strings_as_keyword_only": {
          "match_mapping_type": "string",
          "mapping": {
            "type":         "keyword",
            "ignore_above": 1024
          }
        }
      }
    ],
    "properties": {
      "@timestamp": { "type": "date" }
    }
  }
}

The first template forces any new *_id field to keyword. The second turns every new string field into a pure keyword (no text analysis, no sub-field). This pattern is common for log/event indices where everything is keyword by default.

Disabling Date Detection

Date detection turns strings that look like ISO dates into date fields. It bites when input data has identifiers shaped like dates ("2024-001" etc.):

PUT /my-index
{
  "mappings": {
    "date_detection": false,
    "properties": { "@timestamp": { "type": "date" } }
  }
}

Disable it whenever the input data has non-date fields that happen to look date-shaped.

Monitoring Dynamic Mapping in Production

Pulse tracks dynamic mapping events, field-count growth per index, and cluster-state churn from mapping updates. When a misbehaving producer starts injecting hundreds of unique fields a minute, Pulse's automated root-cause analysis identifies the offending index and the field pattern responsible before the cluster hits its field limit. Connecting your cluster to proactive Pulse monitoring catches mapping explosion early, when it's still fixable without a full reindex.

Common Dynamic Mapping Mistakes

  1. Leaving dynamic: true on a production index ingesting arbitrary JSON. Plan for explosion or set strict.
  2. Not using dynamic templates to force IDs and timestamps into the right types.
  3. Mapping date-like IDs as dates because date detection is on. Disable it for those indices.
  4. Forgetting that nested objects inherit dynamic unless overridden. The root setting cascades.
  5. Trying to change a field's type after dynamic mapping picked the wrong one. You have to reindex.

Frequently Asked Questions

Q: What is dynamic mapping in Elasticsearch?
A: Dynamic mapping is Elasticsearch's auto-detection of new fields at index time. When a document has a field not in the mapping, Elasticsearch infers a type (text+keyword, long, float, date, boolean, object) and adds it. Controlled by the dynamic setting.

Q: How do I disable dynamic mapping in Elasticsearch?
A: Set dynamic to strict (fail on unknown fields) or false (ignore unknown fields) at the index, mapping, or sub-object level. Example: PUT /my-index/_mapping {"dynamic": "strict"}.

Q: What's the difference between dynamic: false and dynamic: strict?
A: false silently ignores new fields - they're kept in _source but not indexed. strict rejects the document with strict_dynamic_mapping_exception. Use strict when unexpected fields are a bug; use false when you want to tolerate but ignore them.

Q: What is a dynamic template in Elasticsearch?
A: A dynamic template is a rule that tells Elasticsearch how to map new fields based on a name pattern (match/unmatch) or detected type (match_mapping_type). Example: map every *_id field as keyword. Templates apply only to dynamically added fields, not explicit ones.

Q: Why does Elasticsearch map my numeric field as text?
A: Because the first document for that field had the value as a JSON string ("42" instead of 42). Once mapped as text+keyword, the type can't change. Either correct the producer to send numbers as numbers, enable numeric_detection, or use a dynamic template to force the type by field-name pattern.

Q: Can dynamic mapping cause cluster instability?
A: Yes. Each new field is a cluster-state update. Bursts of new fields (from misbehaving producers or unbounded JSON) generate cluster-state churn that can stall the master and back up _cluster/pending_tasks. The classic failure mode is mapping explosion past total_fields.limit (default 1000).

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.