A mapping change usually cannot be applied in place, so it means building a new index — and if the application names the index directly, that is a deploy in the middle of a reindex.
# the application only ever queries the alias
POST /_aliases { "actions": [{ "add": { "index": "orders-v1", "alias": "orders" }}]}
PUT /orders-v2 { "mappings": { ... } }
POST /_reindex { "source": {"index":"orders-v1"}, "dest": {"index":"orders-v2"} }
# atomic swap — no window where the alias points at nothing
POST /_aliases { "actions": [
{ "remove": { "index": "orders-v1", "alias": "orders" }},
{ "add": { "index": "orders-v2", "alias": "orders" }}
]}
Both actions in one request is what makes the swap atomic; doing them as two requests leaves a gap where queries fail. Writes arriving during the reindex are the part that needs thought — either dual-write to both indexes for the duration, or reindex again from a timestamp afterwards to catch up. Starting every index behind an alias from day one costs nothing and is the decision that makes all of this possible later.