Hard zalando companies

How do you index a write-heavy catalog without hurting search latency?

The 30 second answer

I batch writes with the bulk API and benchmark the batch size, coalesce repeated updates per product before they reach the cluster, and keep refresh at the freshness the product needs, not lower. For full rebuilds I write to a new index with replicas off, then add replicas and swap an alias. I watch indexing and search thread-pool rejections, merges and refresh time, and throttle ingestion before search suffers.

A large catalog receives price, stock and attribute changes continuously, and the same cluster serves shoppers. The question is really how to keep writes from starving reads. Public candidate reviews from other companies ask the same thing as "what if the system is write-heavy?".

Reduce the work before it reaches Elasticsearch.

  • Coalesce. If one product changes five times in a second, only the last state matters for search. Key the update stream by product id and keep only the latest version per short window, or compare against the last indexed version and skip no-op updates. Every skipped write is a skipped Lucene delete-and-add.
  • Separate lanes. Volatile fields (price, stock) and slow fields (descriptions, attributes) can be updated on different paths, so a burst of description edits cannot delay a price change.
  • Version the writes. With at-least-once delivery, events arrive late or twice. External versioning or a timestamp check makes an older event a no-op instead of overwriting newer data.

Make each write cheaper.

  • Bulk. The docs are direct: "Bulk requests will yield much better performance than single-document index requests." They recommend finding the batch size by benchmark, starting at 100 documents and doubling, rather than guessing a magic number.
  • Refresh interval. A refresh makes changes visible and is costly. The default refreshes every second, and the docs note it only does so on indices that have received a search request recently. A catalog that can tolerate a few seconds of lag can raise refresh_interval; one that promises near-instant price updates cannot, so this is a product decision.
  • Initial loads and full rebuilds. For a bulk load into a new index, the docs suggest setting number_of_replicas to 0 and restoring it afterwards, because the data can be reloaded if a node fails during the load. Combined with an alias swap, this is the standard zero-downtime rebuild.
  • Document ids. Explicit ids force a per-shard check that a document with the same id exists. A catalog needs explicit ids to update in place, so accept that cost and save elsewhere.

Protect search.

  • Watch write and search thread-pool queues and rejections, merge activity and refresh time per index.
  • Throttle or pause ingestion when search latency degrades. Zalando's public outage write-up below lists stopping ingestion as one of the steps that gave its cluster room to recover.
  • Size shards deliberately: too few primaries cap write parallelism; too many small shards waste heap and coordination.

Alternate interview scenarios

"A nightly full reindex makes daytime search slow because it overruns. What do you change?"

Build into a separate new index, ideally on separate nodes or a separate cluster, with replicas at 0 and a relaxed refresh during the load, then add replicas, warm it and swap the alias atomically. Cap the bulk concurrency so the live index keeps its share of disk and CPU, and resume incremental updates from the point the rebuild snapshot was taken so nothing is lost.

"Writes are rejected with 429s during a sale. What does that tell you?"

The write thread pool's queue is full, so the nodes cannot keep up with the indexing rate. Clients should retry with backoff, not hammer. Then I look for the cause: hot shards because of uneven routing, too-small bulk requests, a refresh interval that is too aggressive, or merges falling behind on slow disks.

Sources (4)
  1. Elasticsearch: Tune for indexing speedelastic.co
  2. Elasticsearch API: Bulkelastic.co
  3. Elasticsearch: Size your shardselastic.co
  4. Elasticsearch: Thread pool settingselastic.co