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

Index Architecture

Shards, replicas, segments and the routing that decides which node answers a query.

2 min readIntermediateUpdated Edit this page

Shards and Replicas

An index is divided into primary shards at creation. Each primary can have replica shards, which are full copies serving reads and providing redundancy.

PUT /orders
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "30s"
  }
}

A document is routed to a shard by hash(_routing) % number_of_primary_shards, where _routing defaults to the document id. That formula is why the primary count is immutable: changing it would route existing documents to different shards.

How queries execute

  1. A coordinating node receives the request.
  2. It fans out to one copy of each shard — primary or replica.
  3. Each shard executes locally and returns its top results.
  4. The coordinator merges, ranks and, in the query-then-fetch model, retrieves the documents.

Query latency is therefore bounded by the slowest shard, not the average. More shards means more parallelism and a longer tail. See the tail latency discussion in Shared-Nothing Architecture.

Custom routing

If queries always filter by one field, routing documents by it means a query touches one shard instead of all of them:

POST /orders/_doc?routing=tenant-42
{ "tenant_id": "tenant-42", "total_cents": 19900 }
 
GET /orders/_search?routing=tenant-42
{ "query": { "term": { "tenant_id": "tenant-42" } } }

The trade is skew: a large tenant concentrates on one shard. This is the same bargain as sharding elsewhere.

Segments

Each shard is a set of immutable Lucene segments. New documents create new segments; deletes mark documents in place. Background merges combine segments and physically remove deleted documents.

GET /_cat/segments/orders?v
GET /orders/_stats/segments

Index aliases

An alias is a pointer to one or more indices. Aliases are what make reindexing and rollover transparent to applications:

POST /_aliases
{
  "actions": [
    { "remove": { "index": "orders-v1", "alias": "orders" } },
    { "add":    { "index": "orders-v2", "alias": "orders" } }
  ]
}

The swap is atomic. Applications should always read and write through an alias, never a concrete index name — that single habit is what makes every later structural change possible without downtime.