How does refresh=wait_for on an Elasticsearch index request differ from refresh=true?
answer
- both give read-your-writes, at different prices
- one forces work, one just waits
- think about how many segments get created
- a per-shard listener limit exists
- under load one silently becomes the other
basics
~20 srefresh=wait_for holds the response until the next scheduled refresh makes the change visible, forcing no extra work. refresh=true forces an immediate refresh of the affected shards, creating an extra segment per request and much more merge pressure.
solid answer
~50 sBoth give you read-your-writes on that request; they differ in who pays. `refresh=wait_for` does not trigger anything — it registers a listener and blocks the response until the shard's next refresh happens anyway, so the latency you see is up to `index.refresh_interval` but the cluster does no extra work. `refresh=true` forces the affected shards to refresh right now and only then responds, which is faster for the caller but cuts a new segment per request and drives merge load on a busy index. In practice `wait_for` is the right default for the rare request that genuinely needs immediate visibility, and `true` is reserved for tests or one-off admin operations. One caveat: each shard has a bounded number of pending refresh listeners (`index.max_refresh_listeners`); if a shard exceeds it, further `wait_for` requests fall back to forcing a refresh, so hammering `wait_for` under load degrades into `true`.
go deeper
Remember there is a refresh parameter on write requests with three values, and that wait_for waits for the next scheduled refresh instead of forcing one.
Explain the segment-count consequence: many refresh=true writes mean many tiny segments and merge work, while wait_for lets callers share one refresh.
Show the operational failure mode — the refresh-listener bound turning wait_for into true under load — and argue for fixing the read path or batching instead.
Decide where read-your-writes belongs as a product contract: which flows truly need it, whether it should be served by a real-time get instead, and what visibility latency you publish per index class.
## The problem both options solve Elasticsearch search is near-real-time: a document becomes searchable only once a refresh has turned the shard's in-memory buffer into a Lucene segment, by default about once per second. Some workflows cannot tolerate that: a user saves a record and is immediately redirected to a list view that queries the index, or an integration test asserts on a search straight after a write. The `refresh` parameter on the index, update, delete and bulk APIs exists for exactly these cases. ## The three values - **`refresh=false`** (default) — do nothing extra; visibility happens whenever the next scheduled refresh runs. - **`refresh=wait_for`** — do not trigger a refresh; instead hold this response open until a refresh has occurred that makes this change visible, then respond. - **`refresh=true`** — force an immediate refresh of the shards touched by this request, then respond. ## Why wait_for is usually the better choice The key insight is that a refresh is a *per-shard* operation whose cost is amortised over everything in the buffer. If a hundred writes land in the same second and each one sets `refresh=true`, you have forced up to a hundred refreshes and produced up to a hundred small segments, each of which now has to be merged in the background — CPU, I/O, file handles, and a longer per-query segment list. If those same hundred writes use `wait_for`, they all attach to the same upcoming refresh: one segment, one refresh, and every caller returns at roughly the same moment. The cost of `wait_for` is latency in the caller. The request will block for up to `index.refresh_interval`, so a client that indexes with `wait_for` in a tight loop serialises itself at one document per refresh cycle. The fix there is to batch: send a bulk request with `refresh=wait_for` once rather than N single writes with it. ## The listener limit A shard tracks pending `wait_for` requests as refresh listeners, and the number it will hold is bounded by `index.max_refresh_listeners`. When that bound is exceeded, additional requests do not fail — they fall back to forcing a refresh, i.e. they behave like `refresh=true`. This matters operationally: a system that puts `wait_for` on a high-throughput write path does not stay cheap under load; it degrades into exactly the segment storm you were trying to avoid. ## The standalone refresh API `POST /index/_refresh` refreshes an entire index on demand, independently of any write. It is the natural tool in a test harness (write a batch, refresh once, assert) and in bulk-load pipelines where `index.refresh_interval` was set to `-1` for the duration of the load and you want one refresh at the end. ## What this does not give you Neither value has anything to do with durability. Durability is the translog's job, governed by `index.translog.durability`; a refresh writes segments to the filesystem cache and never fsyncs. A request that returned with `refresh=true` is no more crash-safe than one that returned with `refresh=false`. Equally, neither one gives cluster-wide guarantees beyond the shards involved. `wait_for` guarantees that *this change* is visible when the response arrives; it says nothing about other concurrent writes to other shards. ## Choosing in practice Ask who needs the visibility. If it is a single user-facing flow, put `wait_for` on that one write and leave everything else alone. If it is a test, `wait_for` or an explicit `_refresh` between phases is clean and deterministic — much better than a sleep. If you find yourself wanting it on the majority of writes, the real answer is usually to fix the read path instead: fetch the just-written document by id (the get API is real-time) rather than searching for it.
- What is the latency ceiling a caller sees with refresh=wait_for?Roughly `index.refresh_interval`, since the request waits for the next scheduled refresh — about a second on default settings. If the index has been tuned to 30s, `wait_for` blocks for up to 30s, which surprises teams that tuned the interval for ingestion and then reused the same index in a user-facing flow.
- Your service sets refresh=wait_for on every write and it is fast in staging but causes segment explosions in production. Why?Each shard only holds a bounded number of refresh listeners (`index.max_refresh_listeners`). Once production throughput pushes past that bound, extra `wait_for` requests fall back to forcing a refresh, so the workload behaves like `refresh=true` and cuts a segment per request. Staging never reached the bound.
- Is there a way to get read-your-writes without touching refresh at all?Yes — read the document by id. The get API is real-time and can serve the document out of the translog before any refresh. If the UI flow can fetch the specific record instead of running a search, it needs no refresh parameter and imposes no cost on the index.
saying these in an interview costs you the question
- Says wait_for triggers a refresh immediately
- Claims either option makes the write durable
- Puts refresh=true on the whole production write path
- Assumes wait_for cannot ever force a refresh
- Thinks the parameter guarantees visibility of other concurrent writes