skip to content

In an Elasticsearch mapping, what do the dynamic values true, runtime, false and strict each do?

level: juniorimportance: must knowfreq 72%

answer

  1. Four possible answers to an unexpected field
  2. One of them fails the write outright
  3. One keeps the value visible but unsearchable
  4. One makes it queryable without indexing it
  5. strict raises strict_dynamic_mapping_exception

basics

~20 s

Elasticsearch's dynamic setting decides what happens to an unmapped field: true indexes it and adds it to the mapping, runtime adds it as a query-time field only, false ignores it but keeps it in _source, strict rejects the document.

solid answer

~40 s

`dynamic` controls what Elasticsearch does when a document contains a field the mapping does not know about. **`true`** (the default) guesses a type, adds the field to the mapping permanently, and indexes it. **`runtime`** adds it to the mapping as a runtime field: it is queryable, but computed from `_source` at query time rather than written to the index. **`false`** ignores the field for indexing — the value is still stored in `_source` and comes back in hits, but a query on it matches nothing. **`strict`** rejects the whole document with a `strict_dynamic_mapping_exception`. You can set it at the mapping root or on any individual object field, and inner objects inherit the nearest enclosing value unless they override it. None of these settings affect fields that are already mapped.

code

json · 14 lines
json
PUT /orders
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "order_id": { "type": "keyword" },
      "total":    { "type": "scaled_float", "scaling_factor": 100 },
      "attributes": {
        "type": "object",
        "dynamic": "false"
      }
    }
  }
}

go deeper

for a junior

Memorise the four values and one distinguishing consequence for each, especially that false silently ignores while strict fails the write. Being able to name the default (true) is expected.

for a middle

Explain where the setting lives, that object fields inherit it, and that it can be updated on a live index. Know that a field ignored under false is still in _source and needs a reindex to become searchable.

for a senior

Justify a policy: strict for application-owned indices so a field-name typo fails loudly, a scoped permissive subtree for free-form data. Be ready to say how you would tighten a runaway index without downtime.

for a principal

Frame this as a schema-governance decision across many producers: who is allowed to add fields, whether rejection happens at the ingest edge or at Elasticsearch, and what a permanent unremovable mapping entry costs the cluster.

## What `dynamic` is for Elasticsearch does not require you to declare a schema before indexing. When a document arrives carrying a field name the index mapping has never seen, the index's `dynamic` setting decides the outcome. That single setting is the difference between a friendly development experience and an index whose mapping is written by whatever JSON your upstream happened to send. ## The four values **`true` — the default.** Elasticsearch infers a type from the JSON value, adds the field to the mapping, and indexes it. The mapping change is a cluster-state update processed by the elected master, and once the field exists its type is fixed for the life of the index. **`runtime`.** New fields are added to the mapping as *runtime fields* instead of indexed fields. They are queryable, sortable and aggregatable, but nothing is written to the inverted index or to doc values; the value is derived from `_source` when a query touches it. The field still shows up in the mapping, so it is discoverable, but it costs index size nothing and it can be changed or removed later without a reindex. The trade is query-time cost. **`false`.** The field is simply not added to the mapping and not indexed. Crucially, it is *not* dropped: `_source` is stored verbatim, so the value is returned in search hits and is visible in Kibana's document view — it is just invisible to queries. Candidates routinely mis-state this in both directions. If you later add a real mapping for that field, only documents indexed *after* the mapping change are searchable on it; existing documents need a reindex (or a runtime field, which reads `_source` and therefore sees the old documents immediately). **`strict`.** Elasticsearch refuses the document and returns a `strict_dynamic_mapping_exception`. This is schema-on-write: every field must be declared. It is the right default for a first-class domain index whose producers you control, because it turns a typo in a field name (`user_nmae`) into a loud write failure rather than a silent extra field that quietly enlarges the mapping and never matches a query. ## Where you set it `dynamic` is a mapping property, not an index setting, and it applies at whatever level you place it: - at the mapping root, it governs new top-level fields; - on any `object` field, it governs new sub-fields of that object. Inner objects inherit the nearest enclosing value. That is what makes the common production pattern possible: `strict` at the root for the modelled part of the document, and a single object subtree (`attributes`, `labels`, `custom`) set to `false` or `runtime` where free-form keys are allowed to land. Unlike most mapping properties, `dynamic` can be *changed* on a live index with a `PUT /<index>/_mapping` call — you can tighten a runaway index to `strict` without reindexing, though fields already mapped stay mapped. ## What it does not do `dynamic` only governs *unknown* fields. It has no effect on fields already present in the mapping: `strict` will not reject a document because a mapped field has a wrong-looking value (that is a parse error, governed by the field's type and `ignore_malformed`), and `false` will not stop an existing field from being indexed. It also does not stop *values* you dislike — only unknown *names*. And it is per-index: a template applies it to newly created indices, but an index already created keeps whatever it was born with until you update its mapping. ## Choosing A reasonable default policy: `strict` for indices backing an application feature, where a new field should be a deliberate schema change reviewed like any other; `runtime` or `false` for observability-style data where you want to keep unexpected fields visible but refuse to let them expand the index; `true` only in development and in throwaway exploration indices. The reason to be deliberate is that `true` is not merely permissive — every accepted field is permanent, replicated in cluster state to every node, and unremovable without reindexing.

  • With dynamic set to false, you later add a proper mapping for that field. Are the older documents searchable on it?
    No. Adding a field to the mapping only affects documents indexed afterwards; the older documents were never analysed for that field, so nothing exists in the index for them. You must reindex to make them searchable, or define a runtime field, which reads `_source` at query time and therefore sees the old documents immediately.
  • Can you change dynamic on an index that is already receiving writes?
    Yes. `dynamic` is one of the few mapping properties that can be updated in place with `PUT /<index>/_mapping`, so you can tighten a runaway index to `strict` or `false` without reindexing. It only changes the treatment of fields that are still unknown — everything already mapped stays mapped and keeps being indexed.
  • Does dynamic: strict protect you from a document whose mapped field has the wrong type of value?
    No. `dynamic` governs unknown field *names* only. A document with `"age": "abc"` against a `long` field fails with a mapper parsing exception regardless of `dynamic`, and that behaviour is controlled by the field's `ignore_malformed` parameter instead.

Think of it as a door policy for guests nobody put on the list: true seats them at a permanent table, runtime lets them in but gives them no chair, false leaves them standing outside the room (still visible through the window), and strict cancels the whole party.

saying these in an interview costs you the question

  • Says dynamic false rejects the document like strict does
  • Claims dynamic false strips the field from _source
  • Thinks dynamic runtime indexes the field normally
  • Believes strict also validates values of already-mapped fields
  • Assumes dynamic can only be set at the mapping root

context