skip to content

Explain the Channel capacity options RENDEZVOUS, BUFFERED, CONFLATED, and UNLIMITED, and how each affects send.

level: middleimportance: must knowfreq 60%

answer

  1. RENDEZVOUS=0=default, full backpressure
  2. BUFFERED default 64
  3. UNLIMITED never suspends, OOM risk
  4. CONFLATED keeps only latest, never suspends
  5. CONFLATED = capacity 1 + DROP_OLDEST

basics

~10 s

Capacity controls how many values a channel holds before send has to wait. Rendezvous holds none, buffered holds a few, unlimited holds everything, and conflated keeps only the latest and never waits.

solid answer

~40 s

Capacity is the constructor argument to Channel(capacity). RENDEZVOUS (0, the default) keeps no buffer, so send suspends until a receiver takes the value. BUFFERED uses a small default buffer (64 unless overridden by kotlinx.coroutines.channels.defaultBuffer), and send only suspends once the buffer is full. UNLIMITED gives an unbounded buffer, so send never suspends but you risk OOM if the producer outpaces the consumer. CONFLATED keeps only the most recent value: send never suspends and silently overwrites any undelivered value, so the consumer always sees the latest. You can also pass any positive integer for a fixed-size buffer. The onBufferOverflow parameter (SUSPEND/DROP_OLDEST/DROP_LATEST) further tunes behaviour for fixed buffers; CONFLATED is effectively capacity 1 with DROP_OLDEST.

code

kotlin · 3 lines
kotlin
val c = Channel<Int>(Channel.CONFLATED)
c.send(1); c.send(2); c.send(3)  // none suspend
println(c.receive())             // 3 — only the latest survived

go deeper

for a junior

Names the four modes and that capacity controls buffering.

for a middle

Explains precisely when send suspends for each, and the CONFLATED overwrite semantics.

for a senior

Picks the right capacity per backpressure requirement and explains onBufferOverflow.

for a principal

Reasons about memory/backpressure tradeoffs across a pipeline and default-buffer tuning at scale.

## Capacity: the buffer size The `Channel(capacity)` factory takes a capacity that determines how many elements the channel can hold before a `send` must wait. The named constants live on the `Channel` companion object. ## The four named modes - **`RENDEZVOUS` (= 0, the default)** — no buffer. `send` suspends until a `receive` happens; it is a direct handover. Maximum backpressure: the producer never gets ahead of the consumer. - **`BUFFERED`** — a buffer with a default size (64 elements unless the system property `kotlinx.coroutines.channels.defaultBuffer` changes it). `send` returns immediately while the buffer has room and suspends only when it is full. - **`UNLIMITED`** — a conceptually unbounded (linked-list) buffer. `send` **never** suspends. Convenient, but a fast producer with a slow consumer grows memory without bound — risk of `OutOfMemoryError`. - **`CONFLATED`** — buffer of effectively size 1 that keeps only the **latest** value. `send` never suspends; if a value hasn't been received yet, the new one **overwrites** it (the old value is lost). Great for "I only care about the most recent state." You can also pass any **positive integer** for an exact fixed-size buffer. ## onBufferOverflow For fixed/`BUFFERED` channels you can pass `onBufferOverflow`: - `BufferOverflow.SUSPEND` (default) — suspend the sender when full. - `BufferOverflow.DROP_OLDEST` — evict the oldest buffered element. - `BufferOverflow.DROP_LATEST` — drop the element being sent. `CONFLATED` is semantically `Channel(1, onBufferOverflow = DROP_OLDEST)`. ## Effect on send (summary) ```kotlin import kotlinx.coroutines.channels.Channel Channel<Int>() // RENDEZVOUS: send suspends until receive Channel<Int>(Channel.BUFFERED) // send suspends only when buffer full Channel<Int>(Channel.UNLIMITED) // send never suspends (OOM risk) Channel<Int>(Channel.CONFLATED) // send never suspends, keeps latest only Channel<Int>(capacity = 8) // fixed buffer of 8 ``` ## Choosing one - Need **backpressure** so producer can't outrun consumer → `RENDEZVOUS` or a small fixed buffer. - Smooth out bursty producers → `BUFFERED`. - Only the freshest value matters (sensor readings, UI state) → `CONFLATED`. - You can guarantee the producer is bounded → `UNLIMITED` (use with care).

  • Which capacities make send never suspend?
    UNLIMITED and CONFLATED never suspend send. RENDEZVOUS always may; BUFFERED/fixed suspend only when full (with the default SUSPEND overflow policy).
  • What is the danger of UNLIMITED?
    No backpressure: a producer faster than the consumer grows the buffer unboundedly, eventually causing OutOfMemoryError.

saying these in an interview costs you the question

  • Saying RENDEZVOUS has a small buffer
  • Claiming CONFLATED queues all values
  • Not recognizing the OOM risk of UNLIMITED
  • Thinking BUFFERED is unbounded
  • Confusing capacity with onBufferOverflow

context