I would say that threads work _very well_ for concurrency in _most_ apps. Thread context switches have gotten much much cheaper over the years, and the idea that threads are heavyweight is very outdated.
Coroutines are nice as they allow trivially writing an app which scales to millions of concurrent operations. Rust is nice as it lets us write code for every occasion, async is awful as it poisons the entire ecosystem. The same result could have been achieved with a few tactically inserted yield statements for I/O and locking which are pretty much the only times that async or coroutines help.