Being careful about what functions you call is quite fragile and tedious, and doesn't compose well: what if a library changes when it adds a yield point?
Overall, async/await is a result of people programming like it's 2003, when threads were still very expensive.
For all the complaints about function colouring, I’m glad JavaScript has them. A sync function becoming an async function is a breaking API change. This is much better than the situation in Python, where yield points are invisible.
Sync functions perform better than async functions, and they give more guarantees to the caller. They're strictly better, when you can use them.
If you find yourself making everything async, your design is bad and you should refactoring your code.
With traditional locking, the locked segment is usually very clear. It's possible to use race detectors to verify that objects are accessed with consistent locking. The yield points are also clear.
With async stuff, ANY await point can change ANY state. And await points are common, even sometimes for things like logging. There are also no tools to verify the consistent "locking".
So I often spend hours staring blankly at logs, trying to reconstruct a possible sequence of callbacks that could have led to a bug. E.g.: https://github.com/expo/expo/issues/39428