Explain the three BufferOverflow strategies for buffer() and what each does when the buffer is full.
answer
- SUSPEND = back-pressure, nothing lost (default)
- DROP_OLDEST = evict head, keep freshest, no suspend
- DROP_LATEST = drop newcomer, keep oldest backlog, no suspend
- DROP_* only with finite capacity
- conflate() ~= buffer(1, DROP_OLDEST)
basics
~20 sWhen the buffer fills up: SUSPEND pauses the producer until there is room (nothing lost); DROP_OLDEST throws away the oldest queued item to make space for the new one; DROP_LATEST throws away the new item and keeps what is already queued.
solid answer
~40 s`onBufferOverflow` decides what happens when a new emission arrives at a full buffer. `BufferOverflow.SUSPEND` (the default) applies real back-pressure: `emit()` suspends until the collector frees a slot, so no item is lost and ordering is intact. `BufferOverflow.DROP_OLDEST` evicts the head of the queue (the oldest unconsumed value) and stores the newcomer — you keep the freshest data, useful for live state where stale values don't matter. `BufferOverflow.DROP_LATEST` discards the incoming value and leaves the buffer untouched — you keep the earliest backlog and ignore newer ones. Both DROP_* policies are **non-suspending**, so the producer never blocks. They matter only with a finite capacity; with `Channel.UNLIMITED` the buffer never fills, so overflow policy is irrelevant. `conflate()` is essentially `buffer(0, DROP_OLDEST)` keeping only the latest.
go deeper
Can name SUSPEND, DROP_OLDEST, DROP_LATEST and give a one-line meaning for each.
Correctly distinguishes which items survive each policy and that DROP_* never suspends, while SUSPEND back-pressures.
Maps policies to capacity edge cases (UNLIMITED, capacity 1 == conflate) and picks the right policy for a given workload.
Reasons about latency, memory, and data-loss trade-offs and standardizes overflow policy choices across a system's streams.
## Where overflow comes from `buffer(capacity, onBufferOverflow)` puts a bounded queue between producer and collector. **Overflow** happens when the producer calls `emit()` but the buffer already holds `capacity` items the collector hasn't drained. The `onBufferOverflow` parameter (type `enum class BufferOverflow`) decides the outcome. ## The three policies ### BufferOverflow.SUSPEND (default) The producer's `emit()` **suspends** until the collector consumes an item and frees a slot. This is genuine **back-pressure**: the fast producer is throttled to the collector's pace. - Nothing is dropped; order preserved. - Risk: if the collector is permanently slower, the producer is held back indefinitely. ### BufferOverflow.DROP_OLDEST The **oldest** queued (unconsumed) value is evicted and the new value is enqueued. The producer does **not** suspend. - Keeps the **freshest** N items. - Ideal for "current value" semantics: sensor readings, cursor position, latest UI state. ### BufferOverflow.DROP_LATEST The **incoming** value is discarded; the buffer is left as-is. The producer does **not** suspend. - Keeps the **earliest** backlog; ignores new arrivals while saturated. - Useful when the first events matter most (e.g., keep the first errors, drop the flood that follows). ```kotlin // Keep only the newest 1 value, never suspend the producer: flow.buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) // Bounded backlog of 8; drop new events once saturated: flow.buffer(capacity = 8, onBufferOverflow = BufferOverflow.DROP_LATEST) ``` ## Interaction with capacity - DROP_* policies only ever trigger with a **finite** capacity. With `Channel.UNLIMITED` the buffer never fills, so the policy is moot (and memory can grow unbounded). - `capacity = 0` (`RENDEZVOUS`) is **not allowed together with SUSPEND** for `buffer` in the typical sense, but `buffer(0, DROP_OLDEST)` behaves like `conflate()` — keep only the latest. - `Channel.CONFLATED` is itself shorthand for capacity 1 with DROP_OLDEST. ## Mental model | Policy | Producer on full buffer | What survives | |---|---|---| | SUSPEND | waits (back-pressure) | everything | | DROP_OLDEST | continues | newest items | | DROP_LATEST | continues | oldest items | Choosing wrong corrupts behavior: DROP_OLDEST on an event log loses early events; SUSPEND on a high-rate UI stream can stall the producer or grow latency.
- Which policy does conflate() correspond to?Conflate keeps only the most recent value, equivalent to a capacity-1 buffer with DROP_OLDEST.
- If you use Channel.UNLIMITED capacity, does onBufferOverflow matter?No. An unlimited buffer never fills, so overflow never triggers; the policy is irrelevant (but memory may grow without bound).
saying these in an interview costs you the question
- Saying DROP_OLDEST keeps the oldest values (it keeps the newest)
- Claiming DROP_* policies suspend the producer
- Thinking SUSPEND can lose data
- Believing overflow policy matters with UNLIMITED capacity