No it's not. There are tradeoffs, definitely, and one of them is visible in the article: at the moment doing lifetimes and async is hard. But you don't have to do it, most of the time you use `Arc` or `Arc<Mutex>` and call it a day. In async web frameworks you very rarely need explicit lifetimes, because the workload is mostly isolated - a handler gets an input from the request, you compute the output, you return it. Any shared state is typically behind a shared pointer (like `Arc`).
I feel like this article is written from a perspective of a library author that always starts with going for zero allocations generic API. In production apps you very rarely do that, usually it's plenty fast anyway.
If you default to Arc everywhere, aren’t you essentially just implementing a slow GC?
This type of thing comes up of often when people try the language. They re-implement some part of a program, originally written in a fast GC language, and then wonder why it’s slower.
I feel like the power of the language comes through in specific workloads, or when you take the additional time to avoid naive code. That’s why it is so verbose and rich, it gives you more control. And this is something that advocates often clearly state.
As @therockhead replied already: you won't put every single variable behind `Arc`. It will only be for shared state: queues, handlers that you need to move between threads/tasks etc.
> In async web frameworks you very rarely need explicit lifetimes, because the workload is mostly isolated - a handler gets an input from the request
Was going to post the same comment. Most of my hobbyist Rust programming has been via the Actix Webframework and I only run into the most trivial of borrow checker issues. I guess my projects are not complex or interesting enough :).
I feel like this article is written from a perspective of a library author that always starts with going for zero allocations generic API. In production apps you very rarely do that, usually it's plenty fast anyway.