RelevantSearch.AI
Pattern · Volume 03 · Section F --- Index management · Updated May 2026

Blue/green reindexing with index aliases

Source: Elasticsearch / OpenSearch alias documentation; production methodology for zero-downtime schema evolution

Classification — Pattern for executing schema or analyzer changes without downtime by building the new index alongside the live one and atomically switching.

Intent

Evolve indices (schema changes, analyzer changes, embedding model changes) without downtime by building a new index version alongside the live one, reindexing all data, and atomically switching queries to point at the new version.

Motivating Problem

Schema and analyzer changes require reindexing — existing documents indexed under the old configuration won't work correctly with the new configuration. Naive approaches (delete and recreate the index, with downtime; or in-place mutation, which most engines don't support) either accept downtime or aren't possible. The blue/green pattern allows zero-downtime migration by building the new state alongside the old and switching atomically.

How It Works

The alias primitive. Elasticsearch and OpenSearch (and Solr in different form) support index aliases: named pointers that can target an index. Applications query against the alias (e.g., "products"); the alias resolves to a specific underlying index (e.g., "products_v2024_05_19"). The alias can be atomically reassigned to point at a different underlying index. Queries that arrive during reassignment see a consistent state — they hit either the old or new index, never partial state.

The blue/green workflow. Step 1: build the new index with the new schema or configuration ("products_v2024_05_20"). Step 2: reindex all documents from the old index to the new index using the engine's reindex API (or a custom pipeline that re-reads source data and re-emits to the new index). Step 3: validate the new index has all expected content with the new schema applied. Step 4: atomically swap the alias from old to new. Step 5: keep the old index for some grace period (in case rollback is needed) then drop it.

Reindexing cost. The reindex step is the expensive one. For native reindexing (Elasticsearch _reindex API), cost is proportional to document count and complexity of any transformations. For custom reindexing (re-read source data, re-process, re-emit), cost includes data source access. Either way, reindex of a large corpus takes hours to days. The cost is non-trivial; teams should budget for it as part of any major schema change.

Validation gates. Before swapping the alias, validate the new index: document count matches expected (no docs lost in reindex); spot-check specific documents for correct schema application (the new analyzer produces expected tokens); run a representative query set against the new index and compare results to the old index (changes are expected, but they should be the expected changes); for substantial changes, A/B test the new index with a small traffic fraction before full swap.

Rollback capability. The pattern provides rollback for free: if the new index has issues, swap the alias back to the old index. The rollback is atomic and fast. Keep the old index for a grace period (typically days to weeks after the swap, depending on confidence in the new index and the cost of keeping it). Eventually drop the old index to free storage.

Embedding model migrations. The most expensive blue/green case. Changing embedding models requires re-embedding every document with the new model — substantial LLM API or inference cost. Production migrations: budget the embedding cost explicitly; use batch APIs (50% discount available); execute the embedding in parallel during off-peak hours; maintain old index until new index is validated; consider phased migration (re-embed high-traffic content first, then long-tail).

Partial updates vs reindex. For changes that affect a single field's value (price change, popularity refresh, inventory update), partial updates (the engine's update API) work in-place — no reindex needed. For changes to field types or analyzers, partial updates aren't possible — the field's on-disk representation depends on the original schema. Knowing which changes need reindex and which don't is essential operational knowledge.

Incremental indexing patterns. Production indices receive ongoing updates: new documents, document updates, document deletes. During blue/green reindexing, both the old and new indices must continue receiving updates. The discipline: the indexing pipeline writes to both indices during reindex (dual-write pattern); after swap, the old index can stop receiving updates. The dual-write requirement adds operational complexity but is essential for keeping the new index current during the migration.

When to Use It

Every production indexing pipeline that does any meaningful indexing should support blue/green or equivalent zero-downtime patterns. Schema evolution is part of any maturing system; without zero-downtime capability, schema changes accumulate as deferred work that never gets done.

Alternatives — in-place mutation where the engine supports it (rare for substantive changes). Brief planned downtime for non-critical systems. Application-level dual-source reads during transition (more complex than alias swapping but provides similar capability for engines without alias support).

Sources
  • Elasticsearch alias documentation (elastic.co)
  • OpenSearch alias documentation
  • Elasticsearch _reindex API documentation
  • Production methodology writings on zero-downtime schema migration
Example artifacts

Schema / config

// Elasticsearch blue/green reindexing pattern with aliases

// Step 1: Create new index with new schema
PUT /products_v2024_05_20
{
"settings": { /* new settings */ },
"mappings": { /* new mappings */ }
}

// Step 2: Reindex from old to new (Elasticsearch _reindex API)
POST /_reindex?wait_for_completion=false
{
"source": { "index": "products_v2024_05_19" },
"dest": { "index": "products_v2024_05_20" },
"script": {
"source": "/* optional inline transformation during reindex */"
}
}
// Returns a task ID; monitor with: GET /_tasks/<task_id>

// Step 3: Validate new index
GET /products_v2024_05_20/_count // doc count should match old
GET /products_v2024_05_20/_search // representative queries return
expected results
GET /products_v2024_05_20/_analyze // analyzer behavior matches
expectations
{
"field": "title",
"text": "Sample content for testing"
}

// Step 4: Atomic alias swap - this is the critical step
POST /_aliases
{
"actions": [
{ "remove": { "index": "products_v2024_05_19", "alias":
"products" }},
{ "add": { "index": "products_v2024_05_20", "alias":
"products" }}
]
}
// Queries against alias "products" now hit the new index
atomically
// Either before or after - never partial

// Step 5: Keep old index for grace period, then drop
// After confidence period (typically days to weeks):
DELETE /products_v2024_05_19

// During reindexing: dual-write to BOTH indices to keep them in sync
// Application code:
// def index_document(doc):
// es.index(index="products", document=doc) // via alias - goes to
old
// if migration_in_progress:
// es.index(index="products_v2024_05_20", document=doc) // explicit
new
// After alias swap, the old index can be safely retired

// For embedding model migrations, the reindex step includes
re-embedding:
// The custom pipeline reads each doc from old, re-embeds with new
model, writes to new index

Read in context within Volume 03 →