Adding a field to a mapping is fine. Changing one — a string to a date, an analyzer, a field from analysed to keyword — is not, because the existing documents are already indexed according to the old definition.
# fine
PUT /products/_mapping/product
{ "properties": { "brand_id": { "type": "integer" } } }
# rejected: cannot change the type of an existing field
PUT /products/_mapping/product
{ "properties": { "sku": { "type": "keyword" } } }
The only path is a new index with the new mapping and a reindex into it, which is why every index should sit behind an alias from day one — otherwise the switchover requires a code change or a moment of downtime. Dynamic mapping makes this worse by inferring a type from the first document it sees, so a field that arrives as a string once is a string forever. Turning dynamic mapping off in production is a defensible default.