However, Tokio tries to be the best of both threads and async and sometimes ends up being the worst of both when Sync/Send/etc creep into function signatures.
You can also keep async relatively local to a function that does these things and is itself blocking otherwise.
I do make separate threads when necessary (e.g. to encapsulate blocking I/O).
It can approximate an Erlang experience.
But with a lot more boilerplate and lack of good actor library patterns.