Dynamic mapping infers a type from the first document it sees, which means the schema was decided in 2020 by whichever product was indexed first.
{ "mappings": {
"dynamic": "strict",
"properties": {
"sku": { "type": "keyword" },
"name": { "type": "text", "analyzer": "english" },
"price": { "type": "scaled_float", "scaling_factor": 100 },
"tags": { "type": "keyword" }
}
} }
The field that had been inferred wrong was a product code that looked numeric on the first document and was alphanumeric on most — indexed as a long, then silently rejected for three years. dynamic: strict turns a future inference into an error at index time, which is loud and is what you want; false stores the field without indexing it, which is quiet and is how this happened.