The Big Difference Between Flows and Channels in Kotlin


   Maybe you’ve heard Kotlin programmers say that “channels are hot, flows are cold.”

It’s a useful distinction between two ways of working with an asynchronous data stream. Flows and channels are as different as functions and objects. But that’s not the whole story, because flows themselves come in at least two very different forms. That’s where the limited hot and cold analogy starts to break down.

How can we improve the vague metaphor into something more concrete and actionable?

🔥 We call channels “hot” because they’re stateful objects. A channel is a communication mechanism that lets you receive values from other computations. As the consumer, your interaction with the channel doesn’t necessarily control when that computation starts and stops.

Think of it like the moving escalator on the subway. It’s operating before you start using it and will most likely continue after you leave.

❄️ Flows are called “cold” because they don’t hold state. When you pass a flow around in your Kotlin code, the flow isn’t holding or producing any data. That’s because a Flow object isn’t an active instance of a data stream. Instead, each time you call collect you create a new, ephemeral instance of the flow’s computation that only exists inside that function call.

If a channel is like the moving escalator in the subway station, a flow is more like the elevator. It only starts operating when you start interacting with it and stops again as soon as you leave.

Here