The complexity of an async lib/framework such as i.e. projectreactor stems from that your code stops being linear. And so is the dataflow.
This is the core of the issue. You trade simplicity for performance.
Using futures you can still write simple linear code.
The problem is that thread based execution doesn’t scale well when the threads are mostly waiting for io, such as i.e. an http request.
That is, it was a problem until virtual threads arrived.