However there seems one thing worthwhile to point out:
> All to implement graceful shutdown.
It isn't true that async IO is required for that. Blocking IO calls can also be interrupted via signals. For the use-case of Ctrl+C that is mentioned in the blog post even the simple setup which unblock the syscall and let it return EINTR are successful. But even custom in-application cancellation from different threads works via signals. E.g. building a Thread::interrupt() that unblocks IO on a different thread is possible.
Most classical applications (e.g. proxy-servers) that went for the nonblocking route did it indeed for bigger scalability and lower memory footprint than using a thread per connection model. In the last couple of years and especically in Rust I however feel that most applications choose async either because the library ecosystem forces them or because there's just an assumption of missing out on something if not using it. There's rarely measurements performed with both setups that actually quanitfy any win or loss of using async IO.