System Design Edition Vol. I No. 2
The Developer's Post
Explaining Technology Through the Art of Storytelling
Weather: Clear skies over Kurukshetra battlefield Exchange: 1 Akshauhini = 21,870 Chariots | Weight = θ0 * Global + θ1 * Index Price: Free Press
By Shubham Kumar Section: OpenSearch Branch Date: June 08, 2026

Shard Allocation: Drona's Rules & Shakuni's Dice Calculus

Before the great battle of Kurukshetra began, Bhishma Pitamah lay awake for eighteen nights. He commanded eleven Akshauhinis—vast army divisions of infantry, cavalry, elephants, and chariots. The question that troubled him was deceptively simple: Where should each division be placed?

If he placed too many divisions on the left flank, the right flank would collapse. If he stationed two brothers in the same chariot, a single divine weapon (astra) could wipe out an entire lineage.

In OpenSearch, this strategic battle planning is known as Shard Allocation. Shards are the army divisions, the nodes are the battle sectors, and the supreme commander who coordinates their placements is the AllocationService—our Bhishma Pitamah.

The Kurukshetra Mapping

  • Army Divisions (Akshauhinis): Shards (both primary and replica).
  • Battle Sectors: Nodes in the cluster.
  • Bhishma (Supreme Commander): The AllocationService which orchestrates shard placement.
  • Drona's Rules of Engagement: The AllocationDeciders that enforce routing rules.
  • Shakuni's Dice Calculus: The WeightFunction that calculates optimal placement weight.

Interactive Shard Placement (Vyuha Formation)

SECTOR 1 (NODE A) SECTOR 2 (NODE B) PRIMARY P0 REPLICA R0

Same Shard Decider in Action: The Primary Shard (P0) is assigned to Sector 1. When the Replica Shard (R0) attempts to enter Sector 1, Drona's Decider triggers a veto (blocking shield) to prevent co-location. R0 is then routed to Sector 2.

The Allocation Pipeline

Whenever a node joins, a node leaves, an index is created, or a disk threshold is breached, the war drums sound. This triggers a reroute—recalling Bhishma to redesign the battle formation. Shards flow through a three-stage pipeline to find their home.

1. Drona’s Deciders (Rules of Engagement)

First, every potential node is checked against a series of constraints. Like Drona declaring that a warrior must not attack an unarmed opponent, the AllocationDeciders return YES, NO, or THROTTLE. A single NO vetoes the placement entirely.

Key deciders include:

  • SameShardAllocationDecider: Never put a primary and its replica on the same node (never put two brothers in the same chariot).
  • DiskThresholdDecider: Do not allocate shards to a node whose disk is over 85% full (do not send troops onto sinking mud).
  • AwarenessAllocationDecider: Distribute replica shards across different availability zones (never place all brothers in the same sector).
// AllocationDeciders.java
public Decision canAllocate(ShardRouting shard, RoutingNode node, RoutingAllocation allocation) {
    for (AllocationDecider decider : deciders) {
        Decision decision = decider.canAllocate(shard, node, allocation);
        if (decision == Decision.NO) {
            return Decision.NO; // Vetoed!
        }
    }
    return Decision.YES;
}

2. Shakuni’s Dice (The Weight Function)

Once the deciders filter out invalid nodes, the WeightFunction computes a score for the remaining candidates. Like Shakuni calculating odds with supernatural precision, the balancer evaluates two conflicting factors:

  • Global Balance (theta0): Spreading the overall shard count evenly across all nodes.
  • Index Balance (theta1): Spreading the shards of a specific index evenly, so a single node failure doesn’t lose all copies of an index.

The node with the lowest weight wins the placement.

// BalancedShardsAllocator.java --- WeightFunction
float weight(Balancer balancer, ModelNode node, String index) {
    float weightShard = node.numShards() - balancer.avgShardsPerNode();
    float weightIndex = node.numShards(index) - balancer.avgShardsPerNode(index);
    return theta0 * weightShard + theta1 * weightIndex;
}

Shard States: The Life of a Warrior

Every shard on the battlefield undergoes a journey, transitioning through well-defined states:

  1. UNASSIGNED: The shard has no home (newly recruited troops waiting at camp).
  2. INITIALIZING: The node accepts the shard and begins copying segment files from the primary or local store (receiving weapons and learning the sector).
  3. STARTED: The shard is fully active, indexing data and serving search queries (engaging in active combat).
  4. RELOCATING: The commander orders a shard to move to another node for rebalancing (shifting flanks).

The Unbreakable Vow

Normal zone awareness is a preference: if a zone goes down, replicas can double up in other zones to maintain search availability.

However, Forced Awareness is a vow—like Bhishma's vow of celibacy. If a zone goes down, replicas will remain UNASSIGNED rather than allocate in the same zone. OpenSearch would rather fight with an incomplete army than risk total data loss under a single zone failure.

Rebalancing: Shifting Flanks

As a battle rages, casualties occur and nodes fail, causing the cluster balance to skew. If the weight disparity between the most heavily loaded node and the lightest node exceeds balance.threshold (default 1.0), Bhishma wakes up.

He shifts shards from overloaded nodes to underloaded nodes, ensuring the formation remains stable and resilient to heavy traffic spikes.

Shubham Kumar

Classifieds: The Quorum Balancer Game

A distributed consensus network is forming. Help elect a leader by adjusting the sliders. Identify the minimum number of nodes required for a majority (Quorum) for your selected cluster size.

Total Cluster Size (N): 5 Nodes
Votes for Leader Candidate: 3 Votes
Adjust variables and click "Cast Ballots" to elect the leader.
❖ ❖ ❖