Challenges with asynchronous Rust 265 Why does all this have to be so unintuitive? The answer to that brings us to the topic of common challenges that we all face when programming with async Rust, so let's cover some of the most noticeable ones and explain the reason they exist so we can figure out how to best deal with them. Challenges with asynchronous Rust So, while we've seen with our own eyes that the executor and reactor could be loosely coupled, which in turn means that you could in theory mix and match reactors and executors, the question is why do we encounter so much friction when trying to do just that? Most programmers that have used async Rust have experienced problems caused by incompatible async libraries, and we saw an example of the kind of error message you would get previously. To understand this, we have to dive a little bit deeper into the existing async runtimes in Rust, specifically those we typically use for desktop and server applications. Explicit versus implicit reactor instantiation Info The type of future we'll talk about going forward is leaf futures, the kind that actually represents an I/O operation (for example, Http Get Future ). When you create a runtime in Rust, you also need to create non-blocking primitives of the Rust standard library. Mutexes, channels, timers, Tcp Streams, and so on are all things that need an async equivalent. Most of these can be implemented as different kinds of reactors, but the question that then comes up is: how is that reactor started? In both our own runtime and in Tokio, the reactor is started as part of the runtime initialization. We have a runtime::init() function that calls reactor::start(), and Tokio has a Runtime::new() and Runtime::enter() function. If we try to create a leaf future (the only one we created ourselves is Http Get Future ) without the reactor started, both our runtime and Tokio will panic. The reactor has to be instantiated explicitly. Isahc, on the other hand, brings its own kind of reactor. Isahc is built on libcurl, a highly portable C library for multiprotocol file transfer. The thing that's relevant for us, however, is that libcurl accepts a callback that is called when an operation is ready. So, Isahc passes the waker it receives to this callback and makes sure that Waker::wake is called when the callback is executed. This is a bit oversimplified, but it's essentially what happens.