Kotlin Coroutines & Reactive
The big one, in two parts. On the reactive stack: suspend + WebFlux, coroutine↔Reactor bridging (awaitBody/awaitSingle/mono{}), Flow↔Reactor, structured concurrency, dispatchers, timeouts & retries. Then coroutines in depth: cooperative cancellation, channels & select, Flow back-pressure, hot flows and WhileSubscribed, shared mutable state, CoroutineContext internals, writing your own operators, and the mistakes that only show up under load.
Let’s figure it out.
Ask me about this course or where to start.
- Part I · Coroutines on the reactive stack
- Step 1
The suspend + WebFlux mental model
In WebFlux, suspend doesn't make your handler faster — it lets one thread serve thousands of requests by parking work instead of blocking.
Read lesson - Step 2
Bridging Coroutines and Reactor
Speak both dialects fluently: await a Mono/Flux from suspend code, and wrap suspend code back into a Publisher.
Read lesson - Step 3
Flow ↔ Reactor: Bridging Coroutines and WebFlux
One conversion call turns a Reactor Flux into an idiomatic Kotlin Flow — and back into a streaming WebFlux response.
Read lesson - Step 4
Structured Concurrency in Suspend Handlers
Fan out parallel calls with coroutineScope, survive partial failures with supervisorScope, and let client disconnects cancel everything for free.
Read lesson - Step 5
Coroutine Context & Dispatchers: withContext(Dispatchers.IO)
Suspend functions are a promise not to block — keep that promise by parking blocking calls on Dispatchers.IO.
Read lesson - Step 6
Resilience: Timeouts and Retries with Coroutines and Reactor
A slow dependency is a failing dependency — bound every suspend call with a timeout, then retry it with backoff.
Read lesson - Step 7
Error Handling Across the Bridge: Exceptions, onError, and Fallbacks
A thrown exception and a Reactor onError signal are two faces of the same failure — the bridge translates between them so you can catch what you expect where you expect it.
Read lesson - Step 8
Testing the Reactive Stack: runTest, StepVerifier, and WebTestClient
Asynchronous code deserves synchronous, deterministic tests — and the JVM ecosystem gives you one precise tool for every layer.
Read lesson - Part II · Coroutines in depth
- Step 9
Cancellation is cooperative (and your cleanup is cancelled too)
cancel() does not stop anything. It sets a flag and lets the next suspension point throw — which is why a coroutine that never suspends is a coroutine you cannot stop.
Read lesson - Step 10
Channels: the queue between coroutines
A Flow is a recipe you re-run per collector. A Channel is a real queue with one owner per element — and a capacity policy that decides what happens when it fills.
Read lesson - Step 11
Flow back-pressure: sequential by default, and what buffer() buys
emit() does not return until your collector has finished. That one fact explains every Flow performance question you will ever be asked.
Read lesson - Step 12
Hot flows: SharedFlow, StateFlow, and the WhileSubscribed timeout
StateFlow is a current value, SharedFlow is an event bus, and shareIn's stop timeout is the difference between one websocket and one per screen rotation.
Read lesson - Step 13
Shared mutable state: Mutex, atomics, and confinement
A race does not need two threads. It needs a suspension point between the check and the act — and a single-threaded dispatcher will not save you.
Read lesson - Step 14
Inside CoroutineContext: Job, dispatcher, and carrying an MDC
A CoroutineContext is an immutable set keyed by type, `+` is set union with right-hand override, and every confusing thing about scopes falls out of those two facts.
Read lesson - Step 15
The Flow contract, and writing your own operators
An operator is just an extension function on Flow. The two rules the runtime enforces are what stop you writing a broken one — and both failures are famous.
Read lesson - Step 16
Performance, leaks, and the mistakes that only show up under load
suspend does not mean concurrent, GlobalScope means unowned, and one blocking call on the event loop undoes the entire reactive stack.
Read lesson