Reach for synchronous code first because it is far easier to read, write, and debug. The execution order matches the source order top to bottom. Stack traces point straight at the failing line. There are no callbacks, promises, or event loops to reason about, and errors propagate cleanly with normal try and catch.
The cost is throughput under concurrency. A thread blocked on a synchronous call does no useful work while it waits, so handling many slow operations at once means holding many threads, which burns memory and hits context-switching limits. If you make ten independent API calls one after another and each takes 100 milliseconds, the total is 1000 milliseconds, whereas issuing them concurrently could finish in roughly 100.
A good rule: use synchronous for CPU-bound work, short local operations, scripts, and any logic where the next step genuinely needs the previous result. Switch to asynchronous or concurrent patterns for I/O-bound work at scale, such as a server fielding thousands of simultaneous requests that each wait on a network or database.