ELK Stack — Shards & Replicas

4 minute read

Shards and Replicas

Elasticsearch distributes data across multiple pieces called shards and creates copies called replicas for fault tolerance. Understanding sharding is critical for designing scalable, resilient clusters.

What Is a Shard?

A shard is a self-contained Lucene index — a subset of your Elasticsearch index. When you create an index, Elasticsearch splits it into one or more shards.

┌──────────────────────────────────────────────────┐
│  Index: nginx-logs (3 shards, 1 replica)         │
│                                                   │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐ │
│  │  Shard 0   │  │  Shard 1   │  │  Shard 2   │ │
│  │ (Primary)  │  │ (Primary)  │  │ (Primary)  │ │
│  │            │  │            │  │            │ │
│  │ Docs 1-100 │  │ Docs 101-  │  │ Docs 201-  │ │
│  │            │  │    200     │  │    300     │ │
│  └────────────┘  └────────────┘  └────────────┘ │
└──────────────────────────────────────────────────┘

Why shard?

  • Parallelism — searches run on all shards simultaneously
  • Scalability — shards can be distributed across multiple nodes
  • Size limits — a single Lucene index (shard) has a practical limit of ~50 GB

What Is a Replica?

A replica is a copy of a primary shard on a different node. Replicas serve two purposes:

  1. High availability — if a node dies, the replica takes over
  2. Read throughput — search queries can be served by replicas too
┌─────────────────────────────────────────────────────────┐
│  3-Node Cluster (3 shards, 1 replica)                    │
│                                                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │
│  │   Node 1    │  │   Node 2    │  │   Node 3    │     │
│  │             │  │             │  │             │     │
│  │ Shard 0 (P) │  │ Shard 1 (P) │  │ Shard 2 (P) │     │
│  │ Shard 1 (R) │  │ Shard 2 (R) │  │ Shard 0 (R) │     │
│  └─────────────┘  └─────────────┘  └─────────────┘     │
│                                                          │
│  (P) = Primary shard                                     │
│  (R) = Replica shard                                     │
│                                                          │
│  If Node 1 dies: Shard 0 replica on Node 3 becomes      │
│  primary. No data loss!                                   │
└─────────────────────────────────────────────────────────┘

Setting Shards and Replicas

When creating an index:

$ curl -X PUT -u elastic:changeme123 \
  "http://localhost:9200/my-index" \
  -H "Content-Type: application/json" \
  -d '{
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1
    }
  }'
  • number_of_shards — fixed at creation time (cannot be changed later without reindexing)
  • number_of_replicas — can be changed anytime

Change Replica Count Dynamically

$ curl -X PUT -u elastic:changeme123 \
  "http://localhost:9200/my-index/_settings" \
  -H "Content-Type: application/json" \
  -d '{
    "index": {
      "number_of_replicas": 2
    }
  }'

View Shard Allocation

$ curl -u elastic:changeme123 "http://localhost:9200/_cat/shards/my-index?v"

Expected output:

index    shard prirep state   docs store ip         node
my-index 0     p      STARTED 100  50kb  172.18.0.2 es-node-1
my-index 0     r      STARTED 100  50kb  172.18.0.3 es-node-2
my-index 1     p      STARTED  98  48kb  172.18.0.3 es-node-2
my-index 1     r      STARTED  98  48kb  172.18.0.4 es-node-3
my-index 2     p      STARTED 102  52kb  172.18.0.4 es-node-3
my-index 2     r      STARTED 102  52kb  172.18.0.2 es-node-1

How Many Shards Do You Need?

This is one of the most common questions. Here are the guidelines:

Index Size Recommended Shards Reasoning
< 1 GB 1 shard Over-sharding wastes resources
1-50 GB 1-2 shards Keep shards between 10-50 GB
50-200 GB 2-5 shards Distribute across nodes
> 200 GB Aim for 20-50 GB per shard Balance search parallelism

Rules of thumb:

  • Target shard size: 10-50 GB — shards that are too small waste resources; shards that are too large slow searches
  • Max shards per node: ~1000 — each shard consumes memory and file handles
  • For log indices: 1 shard per daily index is often enough (if < 50 GB/day)
  • Over-sharding is worse than under-sharding — too many small shards create overhead

The Over-Sharding Problem

BAD: 1000 indices × 5 shards × 1 replica = 10,000 shards
     (Each shard uses ~30-50 MB of heap memory)
     (10,000 × 40 MB = 400 GB of heap just for shard overhead!)

GOOD: 1000 indices × 1 shard × 1 replica = 2,000 shards
      (Much more manageable)

Single-Node Clusters and Yellow Health

On a single-node cluster, replicas can never be allocated (no other node to put them on), so cluster health is always yellow:

$ curl -u elastic:changeme123 "http://localhost:9200/_cluster/health?pretty"
{
  "status": "yellow",
  "unassigned_shards": 1
}

Fix for learning/dev: Set replicas to 0:

$ curl -X PUT -u elastic:changeme123 \
  "http://localhost:9200/my-index/_settings" \
  -H "Content-Type: application/json" \
  -d '{ "index": { "number_of_replicas": 0 } }'

Now health will be green.

Shard Routing — How Documents Find Their Shard

When you index a document, Elasticsearch determines which shard it goes to using this formula:

shard = hash(_routing) % number_of_primary_shards

By default, _routing is the document _id. This ensures documents are evenly distributed across shards.

This is why you can’t change number_of_shards after index creation — changing it would break the routing formula and documents would end up in the wrong shards.

Split and Shrink APIs

If you need to change shard count:

Split (increase shards):

$ curl -X POST -u elastic:changeme123 \
  "http://localhost:9200/my-index/_split/my-index-split" \
  -H "Content-Type: application/json" \
  -d '{ "settings": { "index.number_of_shards": 6 } }'

Shrink (decrease shards):

$ curl -X POST -u elastic:changeme123 \
  "http://localhost:9200/my-index/_shrink/my-index-shrunk" \
  -H "Content-Type: application/json" \
  -d '{ "settings": { "index.number_of_shards": 1 } }'

Quick Reference

Concept Key Point
Primary shard Original piece of an index
Replica shard Copy of a primary on a different node
Shard sizing Target 10-50 GB per shard
Shards fixed number_of_shards set at creation (use split/shrink to change)
Replicas dynamic number_of_replicas changeable anytime
Single-node yellow Normal — no node for replicas; set replicas to 0
Over-sharding Too many small shards waste memory; avoid
View shards GET /_cat/shards/my-index?v

Next Step

You understand the storage model. Let’s get hands-on with CRUD operations — creating, reading, updating, and deleting documents.