Elasticsearch Alias Cutover: Ship Breaking Mapping Changes Without Downtime
Changing a mapping often means building a new index. Point your application at an alias, backfill with the reindex API, then flip the alias atomically—without dropping traffic.
17 Nov 2025, 17:12 UTC

The mapping change that forces a rebuild
You need to change the analyzer on a product description field, switch a text field to keyword, or redistribute shards across more nodes. In Elasticsearch, existing field mappings are largely immutable. You cannot simply update them in place. The practical answer is to create a new index with the corrected mapping and move your data—but doing that without downtime is an operational problem, not a data problem.
Point clients at an alias, not an index
The simplest way to decouple your application from physical index names is to hide the index behind an alias. An alias is a secondary name that can point to one index, many indices, or a filtered subset. Your application writes and reads against a fixed alias name such as orders_current. When you need to replace the underlying index, you update the alias, not the application configuration.
This matters because index names tend to encode operational details: version numbers, creation dates, shard counts. Those details change over time. An alias gives you a stable endpoint that survives reindexing, mapping corrections, and shard rebalancing.
The atomic switch
Elasticsearch provides an _aliases API that accepts an array of actions. When you submit multiple actions in a single request, the cluster applies them atomically: either every action succeeds, or none do. That gives you a clean cutover mechanism. You remove the old index from the alias and add the new one in the same request. Readers never see a moment where the alias points to nothing, and writers never have to guess which index is current.
Worked example: orders-v1 to orders-v2
Assume your application reads and writes through the alias orders_current, which currently points to orders-v1. You need a new analyzer on the description field. Run these requests from any HTTP client—Kibana Dev Tools, curl, or your preferred client. You need the manage privilege or equivalent index-level permissions.
First, create the replacement index with the corrected mapping:
PUT /orders-v2
{
"mappings": {
"properties": {
"order_id": { "type": "keyword" },
"description": {
"type": "text",
"analyzer": "english"
}
}
}
}
Next, backfill the data. The _reindex API copies documents from the source index to the destination index. For large indices, add ?wait_for_completion=false so the call returns a task ID immediately, then poll the Tasks API rather than holding the HTTP connection open:
POST /_reindex?wait_for_completion=false
{
"source": { "index": "orders-v1" },
"dest": { "index": "orders-v2" }
}
Check the task status with GET /_tasks/<task_id> before proceeding. For very large backfills, consider slicing the reindex to parallelize the copy and throttling the request rate to avoid saturating the cluster.
Once the reindex completes, perform the atomic switch:
POST /_aliases
{
"actions": [
{ "remove": { "index": "orders-v1", "alias": "orders_current" } },
{ "add": { "index": "orders-v2", "alias": "orders_current" } }
]
}
If this request fails, the alias remains on orders-v1. If it succeeds, traffic immediately resolves to orders-v2. Because the action is atomic, there is no intermediate state where the alias is missing.
The concurrent-write gap
The alias switch is atomic for readers, but the reindex itself is a point-in-time copy. Any documents written to orders-v1 while the backfill runs are not captured unless you handle them explicitly. A one-shot reindex is not change-data capture.
You have three practical options, each with trade-offs:
- Dual-write: Update the application to write to both indices during the migration window. This keeps both indices current but adds latency and complexity, and it does not help if you cannot deploy application code quickly.
- Single write index behind a write alias: Some Elasticsearch versions let you designate one index as the write index for an alias. Writes through the alias go only to that index. You can point the write alias at
orders-v2while the reindex runs, then swap the read alias afterward. Confirm the exact behavior and availability of write-index designation against your target version before relying on it. - Timestamp replay: If your documents carry a reliable
updated_attimestamp, run a second reindex or update-by-query after the bulk copy to capture recent changes. This is simpler than dual-writing but requires a trustworthy timestamp field.
Do not use a filtered alias as an access-control mechanism. Filtered aliases restrict which documents a query can see, but they are not a security boundary. Enforce authorization with role-based security or separate indices.
Verify before and after the flip
Never switch the alias until you have confirmed the new index is ready. Refresh timing can make a freshly written index look stale immediately after cutover, so force a refresh on orders-v2 before the switch:
POST /orders-v2/_refresh
Then compare the old and new indices using the same known query. Run it against orders-v1, against orders-v2, and finally against the orders_current alias. Compare hit counts and inspect a sample of documents to confirm the analyzer change behaves as expected. Also check GET /_cat/aliases/orders_current?v to confirm the alias resolves only to orders-v2 and that no stale write alias remains.
If you used a write alias, verify that the new index is the designated write index and that writes through the alias land only there.
Rollback and cleanup
If you discover a problem after the cutover, the same _aliases API lets you reverse the switch by removing orders-v2 and adding orders-v1. That is only safe if orders-v1 has not been deleted and if no new writes have landed exclusively on orders-v2 that you need to preserve. Once you are confident in the new index, delete the old one to reclaim storage.
Actionable checklist
- Create the replacement index with the corrected mapping and settings.
- Reindex from the old index, using slicing and throttling for large data sets.
- Force a refresh on the new index so recent documents are searchable.
- Compare
_countand a representative query across old, new, and alias endpoints. - Execute the remove/add
_aliasesrequest atomically. - Confirm with
_cat/aliasesand a live query through the alias. - Monitor for errors, then delete the old index when the cutover is stable.
This pattern keeps breaking schema changes routine. The application never learns that the index name changed, and the cutover is a single atomic operation rather than a fragile, multi-step deployment.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.