Elasticsearch Reindex and Aliases
Some index decisions cannot change after creation. Primary shard count, field types, and analyzers stay fixed. Projects outgrow early choices, and the fix always follows the same route: build a new index with better settings, copy the data across, and switch the application over. The Reindex API performs the copy, and aliases perform the switch without any downtime.
The Reindex API
Reindex reads documents from a source index and writes them into a destination index. The destination must exist first, so create it with the new mapping and settings before copying.
PUT /products_v2
{
"settings": { "number_of_shards": 3 },
"mappings": {
"properties": {
"name": { "type": "text" },
"price": { "type": "float" }
}
}
}
POST /_reindex
{
"source": { "index": "products_v1" },
"dest": { "index": "products_v2" }
}
products_v1 products_v2
(old mapping, 1 shard) ───→ (new mapping, 3 shards)
│ │
still serving users being filled in the background
Copying Only Part of the Data
A query inside the source section selects a subset. The script option changes documents on the way through.
POST /_reindex
{
"source": {
"index": "products_v1",
"query": { "term": { "active": true } }
},
"dest": { "index": "products_v2" },
"script": {
"source": "ctx._source.price = ctx._source.price * 1.1"
}
}
Running Large Copies in the Background
Big indexes take minutes or hours. Set wait_for_completion to false, and Elasticsearch returns a task ID immediately. Check progress through the Tasks API.
POST /_reindex?wait_for_completion=false&slices=auto
{ "source": { "index": "products_v1" }, "dest": { "index": "products_v2" } }
Response: { "task": "oTUltX4IQMOUUVeiohTt8A:12345" }
GET /_tasks/oTUltX4IQMOUUVeiohTt8A:12345
The slices=auto setting splits the work into parallel pieces, one per shard. Throughput rises sharply on multi-node clusters.
What an Alias Does
An alias is a second name for one or more indexes. Applications talk to the alias, and the real index behind it can change at any moment. Think of a shop sign that says "Open." Staff swap the actual room behind the door, and customers never notice.
Application ──→ alias "products" ──→ products_v1
POST /_aliases
{
"actions": [
{ "add": { "index": "products_v1", "alias": "products" } }
]
}
The Zero-Downtime Switch
A single _aliases request can remove one index from an alias and add another. Elasticsearch applies all actions in the request as one atomic step. No moment exists where the alias points nowhere.
POST /_aliases
{
"actions": [
{ "remove": { "index": "products_v1", "alias": "products" } },
{ "add": { "index": "products_v2", "alias": "products" } }
]
}
Before: products ──→ products_v1
After: products ──→ products_v2 (switch happens instantly)
The Complete Migration Recipe
| Step | Action |
|---|---|
| 1 | Point the application at the alias "products" |
| 2 | Create products_v2 with the improved mapping |
| 3 | Reindex from products_v1 to products_v2 |
| 4 | Compare document counts of both indexes |
| 5 | Swap the alias in one atomic request |
| 6 | Keep products_v1 for a few days as a safety net, and delete it afterward |
New documents that arrive during the copy exist only in the old index. Pause writes briefly before the swap, or run a second reindex that copies only documents newer than the first run.
Filtered Aliases
An alias can carry a filter. Each alias shows a slice of the same index, which helps multi-tenant systems and department views.
POST /_aliases
{
"actions": [
{
"add": {
"index": "orders",
"alias": "orders_europe",
"filter": { "term": { "region": "europe" } }
}
}
]
}
Write Index and Multiple Indexes
An alias can span several indexes for searching. Only one index may accept writes, marked with is_write_index. Time-based setups use this pattern: searches cover all monthly indexes, while writes go to the newest one.
alias "logs" ──→ logs-2026.09 (read only)
──→ logs-2026.10 (read only)
──→ logs-2026.11 (is_write_index: true)
List every alias with GET /_cat/aliases?v. The output shows which indexes hide behind each name.
Checking the Result
Compare counts after every reindex. A mismatch signals documents that failed to copy, and the response of the reindex call lists failures and version conflicts. Spot-check a few documents by ID in both indexes, and run a handful of real searches against the new index before moving the alias.
GET /products_v1/_count
GET /products_v2/_count
Both responses should show the same count value.
Version conflicts occur when the destination already holds a document with the same ID. Set conflicts to proceed in the request body when a rerun should skip existing documents instead of stopping.
Naming Habits
Treat index names as internal details and alias names as the public contract. Applications, dashboards, and scripts use the alias. Index names carry a version suffix such as _v1 and _v2, so engineers see at a glance which generation serves traffic. This habit turns a risky migration into a routine task.
