Chapter 09 · Dynamic Templates, Index Templates, Component Templates, and Schema Evolution
Dynamic Field Detection, Coercion, Date / Numeric Detection, and Failure Modes from Uncontrolled Input
Observe exactly how new JSON fields become mappings, when coercion or date/numeric detection changes the contract, and why uncontrolled payloads can create irreversible schema mistakes.
Learning outcomes
AtlasMart receives product events from catalog, marketplace and
merchant systems. One feed sends "price":"19.99",
another sends 19.99; an optional merchant field
called launch_date sometimes looks like a date and
sometimes like an arbitrary label. If the first payload silently
decides the mapping, later documents can be rejected
or—worse—accepted under a search contract nobody intentionally
designed. This lesson makes those decisions observable.
Predict how a previously unseen JSON value is dynamically mapped and distinguish detection from coercion.
Explain why date detection and numeric detection are convenience heuristics rather than production schema ownership.
Use dynamic true/false/strict controls and identify the OpenSearch-specific allow-templates modes versus Elasticsearch runtime mode.
Reproduce a mapping conflict and field-growth failure safely, then repair the contract rather than hiding the symptom.
Decide which AtlasMart fields may evolve dynamically and which must be explicit before ingestion.
The reproducible examples target self-managed Elasticsearch
9.5.3 and OpenSearch 3.8.0 using the existing AtlasMart
local-course conventions: Elasticsearch on
https://localhost:9200 with its copied CA certificate,
OpenSearch on https://localhost:9201 with the disposable demo
certificate explicitly treated as local-only, and no moving
latest tags. Template and mapping syntax is verified against
current official documentation. A material product difference
matters here: Elasticsearch 9.5 supports
dynamic: true|false|strict|runtime; OpenSearch
3.8 additionally documents
false_allow_templates and
strict_allow_templates. Do not ship one value to
both products without a compatibility branch.
The generation environment does not run the two search servers, so commands are specified as deterministic labs and expected invariants rather than represented as captured live output. Run them only against the disposable AtlasMart course indices/templates, record the actual API responses from your pinned versions, and never test alias cutover or destructive cleanup against production names.
1. Dynamic mapping is executable schema creation
Mapping is the index-time contract that tells
the engine how each field is parsed, indexed, stored for
sorting/aggregation, and queried. With dynamic mapping enabled,
the first concrete value for a new field can create that
contract. A null value or empty array may create no
mapping at all, so “we sent the field” does not prove “the field
now has a type.”
| Input shape | Typical dynamic consequence | Governance risk |
|---|---|---|
| JSON integer | long | A later decimal may conflict with the first inferred type or lose intended precision policy. |
| JSON floating point | float in default dynamic mapping | Precision may be inappropriate for money; AtlasMart uses scaled_float explicitly. |
| true/false | boolean | String variants can behave differently and should not define the contract accidentally. |
| String matching a detected date format | date when date detection is enabled | An identifier such as 2026-09 can be misclassified as time. |
| Ordinary string | text plus keyword-style multi-field in common defaults | Field may become searchable/aggregatable even when it should be constrained or ignored. |
| Object | object | A later scalar for the same path is a hard mapping conflict. |
Detection decides a field type when no mapping exists. Coercion decides whether a value can be converted to an already-mapped field type. Those are different stages and different failure modes.
2. Reproduce first-document ownership, then inspect the evidence
DELETE atlasmart-schema-detect-v1
PUT atlasmart-schema-detect-v1
{
"settings": {"number_of_shards":1,"number_of_replicas":0},
"mappings": {
"date_detection": true,
"numeric_detection": false
}
}
PUT atlasmart-schema-detect-v1/_doc/first?refresh=true
{
"merchant_code": "10001",
"launch_hint": "2026-09-11",
"price_guess": 19.99,
"promo": {"code":"FALL"}
}
GET atlasmart-schema-detect-v1/_mapping
GET atlasmart-schema-detect-v1/_field_caps?fields=*
The mapping/field-capabilities responses are the evidence. Do
not infer the final type from the original JSON alone. Verify
whether launch_hint became a date,
whether merchant_code stayed a string-derived
field, and how price_guess was inferred on your
exact server version.
3. Coercion can make bad producers look healthy
DELETE atlasmart-schema-coerce-v1
PUT atlasmart-schema-coerce-v1
{
"mappings": {
"properties": {
"stock": {"type":"integer", "coerce":true},
"product_id": {"type":"keyword"}
}
}
}
PUT atlasmart-schema-coerce-v1/_doc/1?refresh=true
{"product_id":"P-9001", "stock":"12"}
GET atlasmart-schema-coerce-v1/_doc/1
If the write succeeds, it proves only that the mapped field accepted the value under current coercion semantics. It does not prove the producer emitted the agreed JSON type. For critical contracts, validate at the producer/API boundary and keep coercion policy explicit. Do not use coercion to compensate indefinitely for upstream schema drift.
Integer coercion may also accept values that are surprising for business semantics. Test the actual boundary values your API permits; the search engine should not be the first validator for money, inventory, tenant identity, or authorization fields.
4. Controlled failures: conflict and field explosion
PUT atlasmart-schema-detect-v1/_doc/conflict
{
"promo": "FALL"
}
The existing promo path was created as an object,
so indexing a scalar at the same path should be rejected.
Capture the HTTP status and root cause. Repair the producer or
route the incompatible payload to a versioned destination; do
not try to “change the field type in place.”
# Pseudocode: do not point this at a shared cluster.
for i in range(1, 501):
document[f"merchant_attribute_{i}"] = "x"
# Observe _mapping growth and index.mapping.total_fields.limit.
# The lesson is the growth curve, not how high you can push the limit.
Unbounded merchant-defined keys multiply mapping metadata, per-segment field structures and cluster-state work. Increasing a field-count limit is not a schema strategy. Prefer an allowlisted explicit schema, a governed dynamic-template family, or a flattened-like representation where the product supports it and query semantics fit.
5. Product-specific dynamic controls are governance tools
| Intent | Elasticsearch 9.5.3 | OpenSearch 3.8.0 |
|---|---|---|
| Accept and map unknown fields | dynamic: true | dynamic: true |
| Keep unknown fields in _source but do not map them | dynamic: false | dynamic: false |
| Reject unknown fields | dynamic: strict | dynamic: strict |
| Create unknown fields as runtime fields | dynamic: runtime | Do not assume the Elastic mode exists; verify supported alternatives. |
| Allow only unknown fields that match dynamic templates | No equivalent dynamic value; design templates plus explicit governance | false_allow_templates / strict_allow_templates are OpenSearch-specific controls |
The names are not cosmetic. They change whether ingestion succeeds, whether a new field is searchable, and whether the mapping changes. Make the selected mode part of the schema artifact and integration tests.
6. AtlasMart decision: explicit core, controlled extension surface
For products, AtlasMart owns product_id,
name, category, price,
available, and updated_at explicitly.
Merchant extensions are accepted only under a documented path
with bounded naming/type rules introduced in the next lesson.
This prevents arbitrary request bodies from mutating the search
contract.
Check your understanding
- What is the difference between detection and coercion?
- Why is numeric_detection a poor substitute for an explicit money mapping?
- What should happen when an object path later receives a scalar?
- Why not simply raise total_fields.limit during field explosion?
- Which dynamic modes are product-specific?
Review the answers
1. Detection chooses a mapping for an unmapped field; coercion converts an incoming value to an already-declared field type when allowed.
2. It infers from string shape and cannot encode the business precision/scaling contract required for currency.
3. Treat it as a schema conflict: reject/quarantine/fix the producer or migrate to a new version; do not mutate the existing field type.
4. It moves the failure boundary while preserving uncontrolled mapping growth and resource/cluster-state cost.
5. Elasticsearch documents runtime mode; OpenSearch documents allow-templates variants. Compatibility requires an explicit branch.
Production judgment
Schema governance starts before the write reaches the cluster. Track rejected-document rate, new-field rate, mapping size, indexing p95/p99, and producer/version identity. A tolerant mapping can improve availability but can also turn upstream defects into expensive permanent index structures. Backups/snapshots protect bytes; they do not make an accidental mapping compatible with a future contract.
Summary and next step
Dynamic mapping is automated schema mutation. You can now distinguish detection, coercion, date/numeric heuristics and product-specific dynamic modes. Next, we replace arbitrary flexibility with ordered dynamic templates that match by type, field name and path.
Authoritative references
- Elastic mapping overview — Dynamic versus explicit mapping and schema-management guidance.
- Elastic dynamic field mapping — Detection rules, dynamic modes, date detection and numeric detection.
- Elastic dynamic templates — match/path/type conditions, template variables, ordering and runtime-field options.
- Elastic templates — Composable index/component templates, precedence, priority and reusable configuration.
- Elastic simulate index template API — Dry-run composition and overlapping-template evidence.
- Elastic simulate index API — Resolve the configuration that a concrete index name would receive.
- Elastic update mapping examples — Why incompatible field-type changes require a new index and reindex.
- Elastic aliases — Index aliases, write-index behavior and no-downtime reindex patterns.
- OpenSearch mappings — Dynamic mapping rules and dynamic-template controls.
- OpenSearch dynamic parameter — OpenSearch-specific dynamic modes including allow-templates variants.
- OpenSearch index templates — Composable templates, priorities and component composition.
- OpenSearch component template API — Reusable settings/mappings/aliases and creation-time behavior.
- OpenSearch simulate index template API — Preview template resolution before index creation.
- OpenSearch reindex API — Source snapshot behavior and destination-index requirements.
- OpenSearch alias API — Alias creation/update APIs and the distinction from manage-alias actions.