ShardsNodesCluster HealthReplicasMaster ElectionSegmentsNear-Real-TimeRefresh

Core Architecture

Shards, nodes, clusters, and how Elasticsearch distributes data for scale, resilience, and near-real-time search.

35 min read9 sections
01

Documents & Indices

Everything in Elasticsearch starts with a document — a JSON object that represents a single unit of data. Documents are the atomic unit of indexing and search. Unlike rows in a relational database, documents are and self-contained.

Anatomy of a Documenttext
# Every document has metadata fields:

{
  "_index": "products",          ← which index this doc belongs to
  "_id": "abc123",               ← unique identifier (auto-generated or explicit)
  "_version": 3,                 ← incremented on every update
  "_source": {                   ← the actual JSON you indexed
    "name": "Running Shoes",
    "price": 129.99,
    "category": "footwear",
    "description": "Lightweight trail running shoes"
  }
}

Key properties:
Documents are JSONnested objects, arrays, all valid
Documents are immutableyou cannot modify a document in place
Updates = delete old version + reindex new version (internally)
_id is unique within an index (not globally)
_source stores the original JSON (retrievable, but not searched directly)

🔑 Immutability is Fundamental

When you "update" a document, Elasticsearch internally marks the old version as deleted and indexes a completely new document. This is because Lucene segments are immutable — once written, they never change. This design enables lock-free concurrent reads and makes crash recovery straightforward.

Indices — Collections of Documents

An index is a collection of documents that share similar characteristics. It's the top-level container — analogous to a , but more flexible. Each index has its own mapping (schema), settings (shard count, analyzers), and data.

Index Conceptstext
Index: "products"
  ├── Mapping (schema): defines field types and analyzers
  ├── Settings: number_of_shards=5, number_of_replicas=1
  ├── Aliases: "products-live""products-v2"
  └── Documents: millions of product JSON objects

Common patterns:
One index per entity type: products, users, orders
Time-based indices: logs-2024-01-15, logs-2024-01-16
Versioned indices: products-v1, products-v2 (swap via alias)

Index naming rules:
Lowercase only
No special characters (except hyphens and underscores)
Cannot start with - or _
Max 255 characters

Index Aliases — Zero-Downtime Reindexing

An alias is a pointer to one or more indices. Clients query the alias, not the index directly. This lets you swap the underlying index without any client changes — essential for zero-downtime reindexing when you need to change mappings.

Alias Swap Patterntext
# Step 1: Create new index with updated mapping
PUT /products-v2
{ "mappings": { ... }, "settings": { ... } }

# Step 2: Reindex all documents from old to new
POST /_reindex
{ "source": { "index": "products-v1" }, "dest": { "index": "products-v2" } }

# Step 3: Atomic alias swap (clients never notice)
POST /_aliases
{
  "actions": [
    { "remove": { "index": "products-v1", "alias": "products" } },
    { "add":    { "index": "products-v2", "alias": "products" } }
  ]
}

# Clients always query "products" aliaszero downtime
# Old index can be deleted after verification

When to Use Aliases

  • Zero-downtime reindexing when mappings change
  • Blue-green deployments for index upgrades
  • Filtering aliases — route queries to a subset of data
  • Time-based rollover — 'logs-current' always points to today's index
  • Multi-tenant isolation — each tenant alias points to their data
1 / 9