Skip to content
Navigation

Type at least two characters. Search covers page titles, headings, tags and database names.

↑ ↓ to navigateEnter to openEsc to close0 pages
Elasticsearch and OpenSearchintermediate

Reindexing

Changing a mapping or shard count without downtime, using reindex, aliases and dual writes.

2 min readIntermediateUpdated Edit this page

Reindexing is how you change anything that cannot be changed in place: a field's type, an analyzer, the primary shard count, or the index's structure.

The alias pattern

// 1. Create the new index with the corrected mapping.
PUT /articles-v2
{ "settings": { "number_of_shards": 6, "refresh_interval": "-1", "number_of_replicas": 0 },
  "mappings": { "properties": { "title": { "type": "text", "analyzer": "english" } } } }
 
// 2. Copy the data.
POST /_reindex?wait_for_completion=false
{
  "source": { "index": "articles-v1", "size": 2000 },
  "dest":   { "index": "articles-v2" }
}
 
// 3. Restore normal settings once the copy is done.
PUT /articles-v2/_settings
{ "index": { "refresh_interval": "1s", "number_of_replicas": 1 } }
 
// 4. Swap the alias atomically.
POST /_aliases
{ "actions": [
    { "remove": { "index": "articles-v1", "alias": "articles" } },
    { "add":    { "index": "articles-v2", "alias": "articles" } }
]}

Disabling refresh and replicas during the copy makes it substantially faster; restoring them afterwards is a step that is easy to forget and expensive to miss.

Monitoring and controlling the task

GET /_tasks?actions=*reindex&detailed
POST /_tasks/<task-id>/_cancel
// Throttle to limit impact on production traffic.
POST /_reindex?requests_per_second=1000

requests_per_second can also be changed on a running task with the rethrottle API.

Keeping the new index current

_reindex copies a snapshot of the source as it was; documents written afterwards are not included. Two ways to close that gap:

Dual write. The application writes to both indices during the migration, then reads switch over. Most control, most application work.

Catch-up reindex. After the bulk copy, reindex documents modified since it started, using a timestamp field:

POST /_reindex
{
  "source": {
    "index": "articles-v1",
    "query": { "range": { "updated_at": { "gte": "2026-07-31T02:00:00Z" } } }
  },
  "dest": { "index": "articles-v2", "op_type": "index" }
}

This requires every document to carry a reliable updated_at, which is worth having anyway.

Remote reindex

POST /_reindex
{
  "source": {
    "remote": { "host": "https://old-cluster:9200", "username": "…", "password": "…" },
    "index": "articles"
  },
  "dest": { "index": "articles" }
}

Requires the remote host to be allowlisted in reindex.remote.whitelist. This is the usual path for a cluster-to-cluster migration or a major-version upgrade.

Verification before the swap

Compare document counts, spot-check documents by id, and run the application's most important queries against both indices, comparing result sets and ordering. Relevance can change when an analyzer changes — that is often the point, and it should still be observed deliberately rather than discovered by users.