Hard zalando search

How do shards and replicas shape query execution and latency?

The 30 second answer

An index is split into primary shards, and each document lives on one of them. A search without routing goes to one copy of every shard, each shard scores locally, and the coordinating node merges the top hits and then fetches the documents. Replicas add read capacity and availability but cost disk and indexing work. Too many small shards adds overhead to every query.

Layout. The Elasticsearch docs: each document belongs to one primary shard, and a replica is a copy of a primary that protects against failure and serves reads. A document's shard is chosen by hashing its routing value, the ID by default.

Query then fetch. A search goes to one copy of each relevant shard. Each shard runs the query, scores locally, and returns its top from + size document IDs and scores. The coordinating node merges them, then fetches the stored fields of the final page from the shards that hold them. Aggregations are reduced on the coordinating node in batches. Zalando's December 2025 post describes this scatter-gather, dedicated coordinating nodes, and adaptive replica selection, which routes each request to the shard copy that has responded fastest recently.

Latency consequences.

  • A query is as slow as its slowest shard, so one hot node raises p99 for everyone.
  • More replicas add read capacity but each still indexes every write.
  • Oversharding adds per-shard overhead to every query and to the cluster state; the shard-sizing guide recommends sizing from data volume and testing, not maximising shard count.
  • Custom routing, for example by market, lets a query hit fewer shards, but can create uneven shards.

Isolation. Zalando's post describes grouping markets into separate clusters so that one market's overload stayed contained, and moving a market to a new cluster using node allocation settings. Separate clusters or indices per market group trade operational cost for blast-radius control.

Guardrails. search.max_buckets limits aggregation buckets and index.max_result_window limits deep pagination. Zalando's incident was caused by an internal client sending far more high-cardinality aggregation queries than usual; its fixes included per-client slow logs via the X-Opaque-Id header and per-client limits. More on that in How do you keep search available when queries or updates overload the cluster?.

Sources (4)
  1. Elasticsearch docs: Clusters, nodes and shards
  2. Elasticsearch docs: Search shard routing and adaptive replica selection
  3. Elasticsearch docs: Size your shards
  4. Zalando Engineering: The Day Our Own Queries DoS'ed Us: Inside Zalando Search (December 2025)