Flow Backpressure & Buffer

Flow Backpressure & Buffer (Deep Explanation)

In Kotlin Flow, backpressure means what happens when the producer emits data faster than the consumer can process it.
Flow is designed to handle this safely and automatically, unlike callbacks or plain channels.


1. What is Backpressure?

👉 Producer → emits data
👉 Consumer → collects data

If:

  • Producer is fast

  • Consumer is slow

➡ Backpressure problem occurs.


2. How Kotlin Flow Handles Backpressure (Default)

By default, Flow is suspending:

flow {
emit(1)
emit(2)
}.collect {
delay(1000)
println(it)
}

🔹 emit() suspends until the collector is ready
🔹 Producer automatically slows down
🔹 ✅ No data loss
🔹 ✅ Safe by default


3. Buffer Operator (buffer)

buffer() allows the producer to emit ahead of the consumer.

flow {
repeat(5) {
emit(it)
}
}.buffer()
.collect {
delay(1000)
println(it)
}

What Happens?

  • Producer fills buffer

  • Consumer processes slowly

  • Improves performance


Buffer with Size

.buffer(capacity = 2)
Capacity Meaning
0 No buffer (default)
1+ Buffered
BUFFERED Default buffer
UNLIMITED ⚠ Risky

4. conflate() (Drop Intermediate Values)

conflate() keeps only the latest value.

flow {
repeat(10) {
emit(it)
delay(100)
}
}.conflate()
.collect {
delay(500)
println(it)
}

Result:

  • Intermediate values dropped

  • Consumer gets latest data only

✅ Best for UI updates


5. collectLatest() (Cancel Previous Work)

Cancels the previous collector when a new value arrives.

flow {
emit(1)
emit(2)
}.collectLatest {
delay(1000)
println(it)
}

➡ If new value comes, old work is cancelled

Real Use Case:

  • Search typing

  • API calls

  • UI rendering


6. debounce() (Wait for Pause)

Emits value after a delay, useful for user input.

flowOf("K", "Ko", "Kot", "Kotl", "Kotlin")
.debounce(300)
.collect {
println(it)
}

✅ Used in search boxes


7. sample() (Emit Periodically)

flow {
while (true) {
emit(System.currentTimeMillis())
delay(100)
}
}.sample(500)
.collect {
println(it)
}

➡ Emits latest value every 500ms


8. flowOn() and Backpressure

flow {
emit("Data")
}.flowOn(Dispatchers.IO)
.collect {
println(it)
}
  • Producer runs on IO

  • Consumer runs on collector context

  • Backpressure still respected


9. Backpressure Operators Comparison

Operator Behavior Use Case
buffer() Queue values Performance
conflate() Drop old values UI updates
collectLatest() Cancel old work Search, API
debounce() Wait for pause Typing
sample() Periodic emit Sensors

10. Flow vs Channel (Backpressure)

Feature Flow Channel
Backpressure Automatic Manual
Data loss Possible
Safety High Medium
Recommended ✅ Yes ❌ Rare

11. Real Android Example

searchFlow
.debounce(300)
.distinctUntilChanged()
.collectLatest {
searchApi(it)
}

✔ Smooth UI
✔ No unnecessary API calls
✔ Proper backpressure handling


Summary

  • Flow handles backpressure by default

  • Use buffer() for speed

  • Use conflate() for UI

  • Use collectLatest() for cancelable work

  • Prefer Flow over Channels

You may also like...