To me Rx is more about monadic composition, push based approach and more important it actually provides IMO an abstraction on top of sync vs async behaviour. Being parametrised over schedulers, allows to write your business logic in a way that is often independent on whether the code is executed synchronously or async (i'm simplifying things a bit here), in some cases allows the consumer to later decide the concurrency model by injecting the proper scheduler, and the built-in testscheduler allows to test the async implementation in unit tests just by plugin a different scheduler (you can time travel etc, something difficult to achieve without a proper abstraction on top of the async mechanism).. not to mention, from a purely pragmatic point of view, the number of built-in Rx operators (deboucing, combineLatest, merge, zip, etc). It's hard to make a comparison with coroutines, to some extend it's kind of asking a comparison between thread executors (and other java concurrency primitives) and rx (even though suspended functions indeed can really provide a way to reason about cooperative tasks)