&gt; Have you been following the Reactive Manifesto [1] and reactive streams [2]? If so, do you have any thoughts on whether this it builds out design practice in a complementary way to your suggestion here, or is it divergent?<p>Reactive streams&#x27; design is the dual to threads&#x2F;fibers&#x2F;continuations, and I believe that as a <i>user facing construct</i> it is the wrong one (I&#x27;ll get to that in a minute), but, as Java does not yet have a standard, built-in implementation of continuations&#x2F;fibers, Reactive Streams is meant as an <i>interoperability standard</i> and does a <i>very good job</i> at that. I like that it exists and I like the spec, which is why Quasar is also RS compliant (turning every stream to a channel and vice-versa).<p>I don&#x27;t like the reactive manifesto, though. It conflates some well-known design practices -- which we simply used to call &quot;robust soft-realtime&quot; -- with a specific implementation (nonblocking), and in the process, overloads a term, &quot;reactive programming&quot;, which has a very different meaning (dataflow, i.e. spreadsheet style). Even Erlang, the inspiration to the manifesto, doesn&#x27;t conform to it (because it discusses implementation). Also, I&#x27;m not too fond of manifestos in general.<p>As to push-based streams, I didn&#x27;t have time to get into that in the talk (the slide is there, though), but I believe that in imperative languages a pull-based API (like channels) is always superior to a push API for several reasons:<p>* It is more general -- both are duals, but going from pull to push only requires a while loop. Going the other way requires adding a queue.<p>* It conveys more information to the developer -- in the push approach, the concurrency is clear: the item is received on the same thread that calls `receive` (the only thing you need is maybe just a tag saying if `receive` itself is thread-safe or not). With a push API, the developer needs to read the documentation to figure out whether the callback can be called on multiple threads concurrently, and, if not, whether it&#x27;s always called on the same thread.<p>* It conveys more information to the library -- a pull API has implicit, automatic backpressure. Calling `receive` means we&#x27;re ready to receive more. With a push API you either don&#x27;t have backpressure, or, like with reactive streams, you need explicit backpressure (`request`) along with more documentation on when `request` may be called. Look how much of the RS spec is devoted to specifying exactly that, and how much shorter it would be if it were a pull API (like Go or Quasar channels).<p>&gt; My concern here would be whether you&#x27;d then be recreating the old problem you mentioned of having many implicitly monadic constructs in imperative programming but no good way of adding your own.<p>Well, yeah, but that&#x27;s a secondary issue. I&#x27;m not a language purist, and you always need to weigh which is better -- a very general abstraction that is then put to use by everyone to create their own incompatible DSLs, or choose the most useful specific abstractions and make sure everyone can read everybody&#x27;s code, even if not everything now has the most elegant expression. For large projects I think the latter is preferable.