Build the mental model
"Mapping explosion" happens when dynamic mapping is left uncontrolled and document structure keeps introducing new fields (for example, storing user-generated key/value data under an object field) — an index's total field count can balloon into the thousands or tens of thousands, and since every field is tracked in cluster state metadata, more fields means falling cluster memory and performance. Guard against this with `mappings.dynamic: false` (ignore new fields entirely rather than indexing them) or the `flattened` field type (treating nested key/value data as a single field). Query patterns matter too — as Lesson 10 explained, `bool` query `filter` clauses are cacheable and should be reused for repeated filters, deep pagination (Lesson 12) should be avoided using `search_after`, and wildcard queries (a leading wildcard like `*keyword*`) should be avoided where possible — a leading wildcard entirely bypasses the inverted index's efficient lookup and effectively scans the whole term dictionary, getting slower as the collection grows. On caching, Elasticsearch itself automatically runs a shard-level request cache (caching identical query-plus-filter combinations) and a filter cache (individual filter clause results) internally — the application side just needs to build consistent query shapes (parameter order and structure) that this built-in caching can actually reuse. Think of it like tuning a car engine for fuel efficiency, trimming unnecessary weight and friction — performance tuning is not one silver bullet, but reducing waste layer by layer across mapping, query pattern, and caching.
Connect it to a real scenario
If the Tutorial Platform stored user comment metadata inside `tutorials` documents as an arbitrary key/value object (like `{"customField1": "x", "customField2": "y"}`), every comment could introduce unique new field names, risking mapping explosion — instead, use the `flattened` field type to hold the whole metadata blob under one field, still accessible at query time through dot-notation. When building the search filter UI, keep reusing Lesson 10's `filter` clause pattern (difficulty, tags) with a consistent structure — if a filter clause's order or structure varies request to request, you lose the opportunity for the shard-level cache to reuse it.
Try the working example
PUT /tutorials
{
"mappings": {
"dynamic": false,
"properties": {
"title": { "type": "text" },
"metadata": { "type": "flattened" }
}
}
}The `metadata` field stores arbitrary key/value data as a single flattened field without field explosion, and `dynamic: false` silently ignores unexpected fields.5-minute try-it
Write a wildcard query using `*cache*` (a leading wildcard), and compare it with an alternative query using `match`/`filter` that could give an equivalent result more efficiently.
One important caution
Leaving dynamic mapping at its default (`true`) and storing user-generated or free-form data under an object field without limits — field count can balloon into the hundreds or thousands, hurting whole-cluster performance.
Using a leading wildcard query (`*keyword*`) as a routine pattern in a production search feature — fast on a small collection, but query latency degrades badly as data volume grows.